HOJ 1232 畅通工程 (并查集)

这里利用生成树中e = n - 1的关系,其中e是边数,n是顶点数。当然e必须是不含重复的,样例中的输入有“重复”的边。在判断过程中,只要判断到是一条边是能把两个不同的集合进行连接,它就是符合条件的这样一条边。计算这样的边数有多少条,我们需要e = n - 1条,故两者差值就是答案。

#include
#include
#include
#pragma warning(disable: 4996)
using namespace std;
const int NN = 1000 + 5;
int n, e, a[NN];
 
int find(int x)
{
	if (x == a[x]) return x;
	a[x] = find(a[x]);//直接更新存储为根节点,能省好多递归浪费的时间
	return a[x];
}

int mer(int x, int y)
{
	if (a[x] == -1) a[x] = x;
	if (a[y] == -1) a[y] = y;
	x = find(x);
	y = find(y);
	if (x != y)
	{
		e -= 1;
		a[x] = y;
	}
	return 1;
}

int main()
{
	int n, m, x, y;
	while (scanf("%d %d", &n, &m) != EOF)
	{
		if (n == 0) break;
		e = n - 1;//生成树中边数e等于顶点数n - 1,利用这个条件进行判断
		memset(a, -1, sizeof(a));
		for (int i = 0; i < m; i++)
		{
			scanf("%d %d", &x, &y);
			mer(x, y);
		}
		printf("%d\n", e);
	}
	return 0;
}

你可能感兴趣的:(HOJ 1232 畅通工程 (并查集))