一道PAT甲级的题目,想请大家帮忙看看我的代码
题目链接:
用了两种方法,DFS和并查集都是一样的结果,测试点0,4,5过不去,实在是不知道哪里错了 ,牛客网上能AC。请各位大神帮忙看看,万分感谢!!!
我的代码1,DFS方法:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXH 17577 #define MAXP 2017 typedef struct PERSON *Person; struct PERSON { char name[4]; int tw; // 这个人的总通话时长 }; typedef struct GANG Gang; struct GANG { int head; // 这个gang的head的哈希值 int tm; // 这个gang的总人数 }; int N, K; int HashTable[MAXH]; // 每个人名字的哈希表,值为这个名字对应的P的下标 int G[MAXP][MAXP]; // 图存储每两人的通话记录 Person P[MAXP]; // 存储每个人数据的数组 int p = 0; // 总人数 int tw = 0; // 当前gang的总通话时长 int tm = 0; // 当前gang的总人数 int head = -1; // 当前gang的head的名字的哈希值 Gang gang[MAXP]; // 存储每个符合条件的gang int gnum = 0; // 满足条件的gang的总数 int entered[MAXP]; // 表示每个人是否被check过,其下标为每个人在P中的下标 int Hash(char name[]) { int h = 0; h += (name[0] - 'A') * 676 + (name[0] - 'A') * 26 + (name[0] - 'A'); return h; } void DFS(int p_s) { int i; // putchar('\n'); // printf("$$now p_s is %s, tw is %d.$$\n", P[p_s]->name, P[p_s]->tw); // if (head != -1) // { // printf("$$now the head is %s, tw is %d.$$\n", P[HashTable[head]]->name, P[HashTable[head]]->tw); // } if (head == -1 || P[p_s]->tw > P[HashTable[head]]->tw) { head = Hash(P[p_s]->name); // printf("$$head has been changed to %s, tw is %d.$$\n", P[HashTable[head]]->name, P[HashTable[head]]->tw); } // putchar('\n'); for (i = 0; i < p; i++) { if (G[p_s][i]) { tw += G[p_s][i]; G[p_s][i] = 0; G[i][p_s] = 0; if (!entered[i]) { tm++; entered[i] = 1; DFS(i); } } } return; } int compare(const void *a, const void *b) { return strcmp(P[HashTable[(*((Gang *)a)).head]]->name, P[HashTable[(*((Gang *)b)).head]]->name); } int main() { scanf("%d %d", &N, &K); int i, j; char name1[4], name2[4]; int w; int h1, h2; int p1, p2; // 初始化 for (i = 0; i < MAXP; i++) { entered[i] = 0; for (j = 0; j < MAXP; j++) { G[i][j] = 0; } } for (i = 0; i < MAXH; i++) { HashTable[i] = -1; } // 读取输入 for (i = 0; i < N; i++) { scanf("%s %s %d", name1, name2, &w); h1 = Hash(name1); if (HashTable[h1] == -1) { // 如果name1是新名字 P[p] = (Person)malloc(sizeof(struct PERSON)); strcpy(P[p]->name, name1); P[p]->tw = w; HashTable[h1] = p; p++; } else { P[HashTable[h1]]->tw += w; } p1 = HashTable[h1]; h2 = Hash(name2); if (HashTable[h2] == -1) { // 如果name2是新名字 P[p] = (Person)malloc(sizeof(struct PERSON)); strcpy(P[p]->name, name2); P[p]->tw = w; HashTable[h2] = p; p++; } else { P[HashTable[h2]]->tw += w; } p2 = HashTable[h2]; if (!G[p1][p2]) { // 需要新加一条边 G[p2][p1] = G[p1][p2] = w; } else { G[p1][p2] += w; G[p2][p1] += w; } } // putchar('\n'); // for (i = 0; i < p; i++) // { // printf("$$Before DFS, %s has tw %d.$$\n", P[i]->name, P[i]->tw); // } // putchar('\n'); for (i = 0; i < p; i++) { if (!entered[i]) { tm++; entered[i] = 1; DFS(i); if (tm >= 3 && tw > K) { gang[gnum].tm = tm; gang[gnum].head = head; gnum++; } } head = -1; tm = 0; tw = 0; } qsort(gang, gnum, sizeof(gang[0]), compare); printf("%d\n", gnum); for (i = 0; i < gnum; i++) { printf("%s %d\n", P[HashTable[gang[i].head]]->name, gang[i].tm); } return 0; }
我的代码2,并查集方法:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXH 17576 #define MAXP 2017 typedef struct PERSON *Person; struct PERSON { char name[4]; int tw; // 这个人的总通话时长 }; typedef struct GANG Gang; struct GANG { int head; // 这个gang的head在P中的下标 int tm; // 这个gang的总人数 }; int N, K; int HashTable[MAXH]; // 每个人名字的哈希表,值为这个名字对应的P的下标 Person P[MAXP]; // 存储每个人数据的数组 int p = 0; // 总人数 int tw = 0; // 当前gang的总通话时长 int tm = 0; // 当前gang的总人数 int head = -1; // 当前gang的head在P中的下标 Gang gang[MAXP]; // 存储每个符合条件的gang int gnum = 0; // 满足条件的gang的总数 int set[MAXP]; // 并查集,存储父结点的下标,下标为每个人在P中的下标 int checked[MAXP]; int Hash(char name[]) { int h = 0; h += (name[0] - 'A') * 676 + (name[0] - 'A') * 26 + (name[0] - 'A'); return h; } int compare(const void *a, const void *b) { return strcmp(P[(*((Gang *)a)).head]->name, P[(*((Gang *)b)).head]->name); } int Find(int v) { if (set[v] < 0) { return v; } else { return Find(set[v]); } } void CompactPath(int d, int s) { // 路径压缩,将d及d所有的孩子的祖先都改成s int i; set[d] = s; for (i = 0; i < p && set[i] != d; i++); if (i < p) { CompactPath(i, s); } return; } void Union(int p1, int p2) { int r1 = Find(p1); int r2 = Find(p2); if (r1 != r2 && set[r1] <= set[r2]) { set[r1] += set[r2]; CompactPath(r2, r1); } else if (r1 != r2 && set[r1] > set[r2]) { set[r2] += set[r1]; CompactPath(r1, r2); } return; } int main() { scanf("%d %d", &N, &K); int i; char name1[4], name2[4]; int w; int h1, h2; int p1, p2; // 初始化 for (i = 0; i < MAXP; i++) { set[i] = -1; checked[i] = 0; } for (i = 0; i < MAXH; i++) { HashTable[i] = -1; } // 读取输入 for (i = 0; i < N; i++) { scanf("%s %s %d", name1, name2, &w); h1 = Hash(name1); if (HashTable[h1] == -1) { // 如果name1是新名字 P[p] = (Person)malloc(sizeof(struct PERSON)); strcpy(P[p]->name, name1); P[p]->tw = w; HashTable[h1] = p; p++; } else { P[HashTable[h1]]->tw += w; } p1 = HashTable[h1]; h2 = Hash(name2); if (HashTable[h2] == -1) { // 如果name2是新名字 P[p] = (Person)malloc(sizeof(struct PERSON)); strcpy(P[p]->name, name2); P[p]->tw = w; HashTable[h2] = p; p++; } else { P[HashTable[h2]]->tw += w; } p2 = HashTable[h2]; Union(p1, p2); } int j; for (i = 0; i < p; i++) { if (!checked[i] && set[i] <= -3) { checked[i] = 1; tw = P[i]->tw; tm = -1 * set[i]; head = i; for (j = 0; j < p; j++) { if (!checked[j] && Find(j) == i) { tw += P[j]->tw; checked[j] = 1; if (P[j]->tw > P[head]->tw) { head = j; } } } if (tm >= 3 && tw > 2 * K) { gang[gnum].tm = tm; gang[gnum].head = head; gnum++; } } } qsort(gang, gnum, sizeof(gang[0]), compare); printf("%d\n", gnum); for (i = 0; i < gnum; i++) { printf("%s %d\n", P[gang[i].head]->name, gang[i].tm); } return 0; }