您的位置:首页 > 其它

POJ 1611 The Suspects 并查集

2013-05-09 22:15 141 查看
大学里总共有n个学生,m个社团。学生的编号从0到(n-1)。每个学生可以参加多个社团。现在0号学生疑似感染了SARS。与疑似感染者同一个社团的人都是疑似感染者。求疑似感染者总数。

这是一个简单的并查集题目。初始时,每个学生都各是一个集合。然后把同一社团的学生都合并到同一集合去。完成合并后,0号学生所在的集合的元素个数即是疑似感染者总数。

#include <stdio.h>
#define MAX 30005
//并查集
//还有一种设置并查集的办法:将father[]都初始化为-1,然后利用祖宗的father[]记录负的集合元素数。
int father[MAX];

int findset(int x)
{
int fx = x,tmp;
while(fx != father[fx])//找到x的最老的祖宗
fx = father[fx];
while(x != father[x])//路径压缩:把x的各级father都置为最老的祖宗
{
tmp = father[x];
father[x] = fx;
x = tmp;
}
return fx;
}

void unionset(int x,int y)
{
x = findset(x);
y = findset(y);
if(x < y)//让编号最小的成为最老的祖宗,这是为了让0号学生成为代表元素
father[y] = x;
else
father[x] = y;
return;
}

int main()
{
int m,n,k,i,j,suspects,tmp1,tmp2;
//FILE *fp = NULL;
// if(NULL == (fp = fopen("t.txt","r")) )
// printf("cannot open file.\n");
while(1)
{
suspects = 0;
//fscanf(fp,"%d %d",&n,&m);
scanf("%d %d",&n,&m);
if(0 == m && 0 == n)
break;
if(0 == m)
{
suspects = 1;
printf("%d\n",suspects);
continue;
}
for(i=0;i<n;i++)//make set
father[i] = i;
for(i=0;i<m;i++)
{
//fscanf(fp,"%d",&k);
scanf("%d",&k);
//fscanf(fp,"%d",&tmp1);
scanf("%d",&tmp1);
for(j=1;j<k;j++)
{
//fscanf(fp,"%d",&group[j]);
scanf("%d",&tmp2);
unionset(tmp1,tmp2);
}
}
for(i=0;i<n;i++)
//if(0 == father[i])
if(0 == findset(i))
suspects++;
printf("%d\n",suspects);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: