https://vjudge.net/contest/375481#problem/G
一开始想复杂了,后来发现完成了连接集合后 只要在p[]数组上找异常点即可
总体思路:1.初始化并查集 写出并查集的板子
2.给每一组数并成一个集合 我是把每组的第一个数当做每组数的祖宗节点
3.在遍历p,在p【i】中找祖宗节点与0祖宗节点相同的点
注意:在合并集合的操作是p[find(a)]=find(b) 相当于是对各自的祖宗节点在进行操作,所以一旦同组中有传染的人到了其他组 会自动做连接 即直接改变他们的祖宗节点 让首次感染组合其他感染组共用一个祖宗节点(即感染节点)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=3e4+10;
int n,m;
int p[N],cnt,q[N];
int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main()
{
while(cin>>n>>m)
{
if(n==0&&m==0) break;
else
{
for(int i=0;i<n;i++)
{
p[i]=i;
}
int cnt=0;
while(m--)
{
int k;
cin>>k;
for(int i=0;i<k;i++)
{
cin>>q[i];
p[find(q[i])]=find(q[0]); //连接起来 同时要是碰到0,本集合所有点都会自动记上(find(0)可以实现)
} //以及可以更改在其他集合中的本集合的点的祖宗节点(本集合指0集合)
}
for(int i=0;i<n;i++) //直接遍历p 在p里找根节点和0相同的点
{
if(find(i)==find(0))
{
cout<<i<<" ";
cnt++;
}
}
cout<<cnt<<endl;
}
}
return 0;
}