并查集水题,没有啥注意的地方,题目意思大概是非典来袭问你有多少个人和编号0的学生有联系,联系指只要你朋友的朋友的朋友的朋友的。。。。朋友是0的话,这些人全算,所以是个并查集问题
第一行n,m。n代表总学生人数,m代表多少个集合(学生有联系的团体),第二行第一个是这个集合有多少人(num),后面num个学生的编号。把所有集合进行并查集操作后,再一一进行计数,只要这些人的头节点和0的头节点是一样的,ans就加一。
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=30050;
int par[MAXN],rank[MAXN];
void init()
{
for(int i=0;i<MAXN;i++)
{
par[i]=i;
rank[i]=0;
}
}
int find(int x)
{
if(x==par[x])
return x;
else
return par[x]=find(par[x]);
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return;
if(rank[x]<rank[y])
par[x]=y;
else
par[y]=x;
if(rank[x]==rank[y])
rank[x]++;
}
int main()
{
int n,m;
int num;
int pos;
int a;
while(cin>>n>>m)
{
init();
if(!n&&!m)
break;
while(m--)
{
cin>>num>>pos;//把pos当跳板,后面每个数字都和这个链接
for(int j=1;j<num;j++)
{
cin>>a;
unite(pos,a);
}
}
int ans=0;
for(int i=0;i<n;i++)
if(find(i)==find(0))
ans++;
cout<<ans<<endl;
}
return 0;
}