poj-1611
题意:有很多组学生,在同一个组的学生经常会接触,也会有新的同学的加入。但是SARS是很容易传染的,只要在有一位同学感染SARS,那么该组的所有同学都被认为得了SARS。现在的任务是计算出有多少位学生感染SARS了。假定编号为0的同学是得了SARS的。
#include <iostream>
using namespace std;
#define maxn 30005
int n, m, k, t, f, fa[maxn], r[maxn], a, b;//fa[]是根节点,r[]是 根节点的高度
int find(int x) //查找根节点
{
if (x == fa[x]) //由父节点继续向上递归查询
return x;
else
return fa[x] = find(fa[x]); //找到其祖先节点,并将其父节点变成找到的祖先节点
}
void un(int x, int y)//分别查询两点的根节点。
{
a = find(x);
b = find(y);
if (a == b)
return;
if (r[a] > r[b]) //如果二者的祖先节点不一致,那么选择高度更高的为根节点,保证同集合。
fa[b] = a;
else
{
fa[a] = b;
if (r[a] == r[b])
r[b]++;
}
}
int main()
{
int i, sum;
while (cin >> m >> n && (m || n))
{
for (i = 0; i < m; i++) //先将自身作为根节点。
{
fa[i] = i;
r[i] = 0;
}
for (i = 0; i < n; i++) //给出集合每个集合人数,以及第一个人的编号
{
cin >> k;//k为人数,f为第一个人的编号
if (k >= 1)
cin >> f;
for (int j = 1; j < k; j++)
{
cin >> t;
un(f, t);
}
}
sum = 1;
for (i = 1; i < m; i++)
{
if (find(i) == find(0))
sum++;
}
cout << sum << endl;
}
}