参考教程:
此题的代码在洛谷p1551的基础上做了合并时优化:查看洛谷p1551题解
/*
并查集,使用depth数组优化了集合合并,降低了查找时的时间复杂度
*/
#include <stdio.h>
int city[1000];
int depth[1000]; //新增depth数组,记录节点处树的深度
void init()
{
for (int i = 1; i < 1000; i++)
{
city[i] = i;
depth[i] = 1;
}
}
int find(int x)
{
while (city[x] != x)
{
x = city[x];
}
return x;
}
int main()
{
int n, m;
while (~scanf("%d", &n))
{
if (n != 0)
{
init();
scanf("%d", &m);
while (m--)
{
int a, b;
scanf("%d%d", &a, &b);
int roota = find(a);
int rootb = find(b);
if (roota != rootb) //如果两个根不相同,说明两个元素在不同的集合,修路后合并为一个集合,集合总数n减1
{
/*
选择把深度小的树连接到深度大的树上
*/
if (depth[roota] <= depth[rootb])
{
city[roota] = rootb;
}
else
{
city[rootb] = roota;
}
if (depth[roota] == depth[rootb]) //若两树深度相同,则连接后树的深度会加1
{
depth[rootb]++;
}
n--;
}
}
printf("%d\n", n - 1);
}
else
{
break;
}
}
return 0;
}