POJ-1611 The Suspects (并查集)
原题链接:http://poj.org/problem?id=1611
题目大意:
将学生逐一编号,并分成 k 个小组,有传染病SARS,只要小组中有传染源,则整个小组的人均被感染,求最终感染者人数。(注:起始 0 为感染源)
分析:
根据题目的大意易知,只要与 0 号学生有关系的都为感染者,即与 0 号学生同一组的人数即感染者人数。易想到 并查集 和 建树遍历 。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int father[30010];
int root(int x) //找到 x 的根节点
{
while (father[x]!=x) //while -- 找到根节点的值, 若改为 if 只能找到上一个节点的值
x=father[x];
return x;
}
void build(int x,int y)
{
int x1,y1;
x1=root(x);
y1=root(y);
if (x1!=y1)
{
if (x1==0) father[y1]=x1; //若 x 的根节点 x1 为 0 ,则 y 的根节点与 x 建立关系,其根节点也应为 0
else father[x1]=y1;
}
}
int main()
{
int n,m;
while (cin>>n>>m)
{
memset (father,0,sizeof(father));
if (n==0&&m==0) return 0;
for(int i=0;i<n;i++) father[i]=i;//学生逐一编号
while (m--)
{
int k,a;
cin>>k>>a;// a 为每一行的根节点
for (int i=1;i<k;i++)
{
int b;cin>>b;
build(a,b);//逐一对行内的点建立连接
}
}
int ans=0;
for (int i=0;i<n;i++)
{
if (root(father[i])==0) ans++;
}
cout<<ans<<endl;
}
}