一道PAT甲级的题目,想请大家帮忙看看我的代码
题目链接:

用了两种方法,DFS和并查集都是一样的结果,测试点0,4,5过不去,实在是不知道哪里错了
,牛客网上能AC。请各位大神帮忙看看,万分感谢!!!
,牛客网上能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;
}
