题解 - The Suspects
misaka_八重樱 · · 题解
这题是一个纯并查集题
从“如果一个群体中有一个人是非典患者,那么这个群体中的所有人都是非典患者。”这句话可以简化成有多个集合,求与0在同一个集合里的所有人数
先给个find函数路径压缩
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
对并查集不熟的小伙伴可以百度一下,这里推荐一个,本人认为讲的很不错
并查集
一个群体中的合并操作
if(find(x)!=find(y)) f[f[x]]=f[y];//如果x与y不在同一集合中,将祖先和祖先合并即可使两集合合并
直接上代码
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int f[30050];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);//路径压缩
}
int main()
{
while(1)
{
int n,m;
cin>>n>>m;
if(n==0&&m==0) break;
for(int i=0;i<n;i++)
f[i]=i; //先全部初始化为自己,即为自己就是一个集合
for(int i=1;i<=m;i++)
{
int num;cin>>num; //人数
int x;cin>>x; //先输第一个数,方便合并
for(int j=2;j<=num;j++)
{
int y;cin>>y;
if(find(x)!=find(y)) f[f[x]]=f[y];//第一个和后面输入的挨个合并
}
}
int ans=0;
for(int i=0;i<n;i++)
if(find(0)==find(i)) ans++; //如果查找0的祖先是某个编号的祖先时,说明这个人会被0感染,计数器+1
cout<<ans<<endl; //输出会被感染的人数
}
return 0;
}