题意:
找出所有与小A同学(编号为0)直接或间接接触过的同学。多组数据,每组数据第一行为n和m(0<n<=30000,0<=m<=500),n是学生的数量,m是学生群体的数量。之后m行,每行有一个整数num即小团体人员数量,随后有num个整数代表这个小团体的学生。
思路:
使用并查集来解决问题。若学生在同一个小团体里,则将它们所在的并查集合并。最后只需要输出编号为0的并查集里面有多少成员即可。
并查集要路径压缩,防止超时。
总结:
一道很简单的并查集题目。唯一要点就是路径压缩。
代码:
#include <iostream>
using namespace std;
//并查集
int par[30000],rnk[30000];
void init(int n)
{
for(int i=0;i<n;i++)
par[i]=i,rnk[i]=1;
}
int find(int x)
{
return par[x]==x?x:par[x]=find(par[x]);
}
bool unite(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return false;
if(rnk[x]>rnk[y])
par[y]=x,rnk[x]=(rnk[y]+=rnk[x]);
else
par[x]=y,rnk[y]=(rnk[x]+=rnk[y]);
return true;
}
int main()
{
int n,m;
while(1)
{
cin>>n>>m;
if(n==0&&m==0)
break;
init(n);
for(int i=0;i<m;i++)
{
int num;
cin>>num;
int a[num];
for(int j=0;j<num;j++)
cin>>a[j];
for(int j=1;j<num;j++)
unite(a[j-1],a[j]);
}
cout<<rnk[find(0)]<<endl;
}
}