您的位置:首页 > 其它

pku1611

2011-05-03 11:37 176 查看
嘿嘿,第一道并查集的题目,一个基本的应用,求一个集合的元素个数,不过中间同样涉及了俩个基本的操作,查找还有合并

题目大意:有n个学生(标号为0 to n-1),m个学生社团,给出每个社团里所有学生的标号,并假设0号学生患有SARS(社团里只要用一个学生患病,则整个社团里的学生都会被隔离),问最后一共会有多少学生被隔离?
这是一个最基础的并查集的应用,扫描每一个社团,只要两个学生出现在同一个社团,则将这两个集合合并起来,最后输出0号点所在集合的rank值集合(rank值记录这个集合中的元素个数并用一个flag值跟踪0号元素所在集合标号)即可。

#include<stdio.h>
#define MAXN 30010
int f[MAXN],r[MAXN],flag;
//f[x]表示元素f的父节点
////由于不知道应该将子树挂到那个集合上面去,故需要一个准则,这里的准则是将子树挂到
////r值大的集合上面去,初始状态下r数组的值均为一,代表每个分支下只有一个数字
//flag用来追踪0号学生所属集合
int find(int x)
{
if(x==f[x])
return f[x];
f[x]=find(f[x]);
return f[x];
}//路径压缩
void Union(int x,int y)
{
int a=find(x);
int b=find(y);
if(a==b) return ;
if(r[a]<=r[b])
{
f[a]=b;
r[b]+=r[a];
if(a==flag)
flag=b;//扩大0号学生的感染范围,b为0号学生所属集合的父节点
}
else {
f[b]=a;
r[a]+=r[b];
if(b==flag)
flag=a;
}
return ;
}
int main()
{
int i,j,n,m,temp1,temp2,num;
while(scanf("%d %d",&n,&m)!=EOF &&(n||m))
{
flag=0;
for(i=0;i<n;i++)//有0号学生,所以这里i必须从0开始
{
f[i]=i;
r[i]=1;
}
for(i=1;i<=m;i++)
{
scanf("%d",&num);
for(j=1;j<=num;j++)
{
if(j==1)
{
scanf("%d",&temp1);
}
else {
scanf("%d",&temp2);
Union(temp1,temp2);
}
}
}
printf("%d\n",r[flag]);//输出集合中的元素个数
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: