传送门:poj 1611
题意:有一群人和很多组,每个人可能属于很多组,0号患了传染病,和他一组的人都被列为怀疑对象,和怀疑对象一组的也是怀疑对象。
并查集维护就好了,需要注意的是并查集中0号所在的树必定要0号当主根,这样最后才好统计人数。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int f[30005];
int getf(int k)
{
return k==f[k]?k:f[k]=getf(f[k]);
}
int a[30005];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)&&m+n)
{
int t;
for(int i=0;i<n;i++)
f[i]=i;
for(int i=0;i<m;i++)
{
scanf("%d",&t);
for(int j=0;j<t;j++)
{
scanf("%d",&a[j]);
if(j>0)
{
if(getf(a[j-1])==0)//如果前一个结点的根是0号,那么就将当前点向左归并进去。
f[getf(a[j])]=getf(a[j-1]);
else
f[getf(a[j-1])]=getf(a[j]);//否则的话就一直让右边的点当主根,因为前面没有0,那么0只有可能在右边。
}
}
}
int ans=0;
for(int i=0;i<n;i++)
if(getf(i)==0)
{
//printf("%d ",i);
ans++;
}
printf("%d\n",ans);
}
return 0;
}