题目连接
http://acm.hust.edu.cn/vjudge/problem/10536
Sample Input
100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0
Sample Output
4
1
1
题意
0号学生是,非典传染源,与他同组的学生都有感染非典的嫌疑,找出所有有嫌疑的学生。
题解
标准的并查集,可以把rank[0]设置得特别大,然后所有与他有关联的学生都向他连根,还有就是原则上每组的其他人都与第一个人进行Union。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<string>
#include<cctype>
#include<algorithm>
#include<vector>
int father[30005];
int rank[30005];
int start(int n)
{
for(int i=0;i<n;i++)
{
father[i]=i;
rank[i]=0;
}
}
int find(int x)
{
if(x!=father[x])
{
father[x]=find(father[x]);
}
return father[x];
}
void unin(int x,int y)
{
int fatherx=find(x);
int fathery=find(y);
if(fatherx==fathery)return ;
if(rank[fatherx]<rank[fathery])
{
father[fatherx]=fathery;
//rank[y]++;
}
else
{
father[fathery]=fatherx;
if(rank[fatherx]==rank[fathery]) rank[fatherx]++;
}
}
int main()
{
int p,q;
while(scanf("%d%d",&p,&q)!=EOF)
{
if(p==0&&q==0)break;
start(p);
rank[0]=1e9;
for(int i=0;i<q;i++)
{
int t;
scanf("%d",&t);
int k,kk;
int kkk;
scanf("%d",&kkk);
for(int j=0;j<t-1;j++)
{
scanf("%d",&kk);
if(find(kkk)!=find(kk))unin(kkk,kk);
}
}
if(q==0){printf("1\n");continue;}
int cnt=1;
for(int i=1;i<=p-1;i++)if(find(i)==0)cnt++;
printf("%d\n",cnt);
}
return 0;
}