题目大意:求出被非典病毒感染的人,并查集模板题。结点是每一个人,根节点是任意一个社团的一个人。
只要找出和0编号的人在一个集合的人即可。
#include<iostream>
using namespace std;
int rank[30005],num[30005],father[30005];
void make_set(int n)
{
for(int i=0;i<n;i++)
{
rank[i]=0; //每一棵树的秩,也就是树的路径长度(树的高度或者深度-1)
num[i]=1; //设置根节点的所在树的全部节点数
father[i]=i;
}
}
int find_set(int x)
{
if(x!=father[x])
{
father[x]=find_set(father[x]); // 通过回溯把每一个结点的根节点都指向同根节点
}
return father[x];
}
void uni_set(int x,int y)
{
x=find_set(x);
y=find_set(y);
//cout<<" X "<<x<<" Y "<<y<<endl;
if(x==y) //如果在同一集合则无需合并。
return;
if(rank[x]>rank[y]) //反之则把矮树合并到高树上去
{
father[y]=x;
num[x]+=num[y];
}
else{
if(rank[x]==rank[y]) //如果同样高度,则随意
rank[y]++;
father[x]=y;
num[y]+=num[x];
}
}
int main()
{
int n,m,k,a,b;
while(scanf("%d%d",&n,&m)&&(n||m))
{
make_set(n);
for(int i=0;i<m;i++)
{
scanf("%d",&k); //题目中的每一个社团是一个集合,如果集合之间没有任一个元素交集,那么就是独立的一棵树,反之就会归入到同一棵树
scanf("%d",&a);
for(int j=1;j<k;j++)
{
scanf("%d",&b); //流程:在初始化后边加入边合并,在合并中查找,查找完再合并
uni_set(a,b);
a=b;
}
}
int temp=find_set(0);
//printf("temp %d\n",temp);
printf("%d\n",num[temp]);
}
system("pause");
return 0;
}