第三次-J-poj-1611-并查集

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;
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43866317/article/details/86662350