现在我们来说另一种求最小生成树的方法——克鲁斯卡尔算法,我们知道最小生成树中不能有回路,所以遇到形成回路的边就跳过,但是我们怎么知道会形成回路呢?这时我们就要判断两个顶点是否连通,判断连通的方法有深搜和广搜,但他俩效率都比较低,更高效的方法就是并查集。
将所有顶点放入到一个并查集中,判断两个顶点是否连通,只需判断两个顶点是否在同一个集合中(即是否有共同的祖先)即可。
先来说说并查集,当读入一个连通边(u,v)时,先判断u和v是否在同一个集合中,如果是则不用合并;如果不是,则用一个合并(Union)运算把u、v所在集合合并,使得这两个集合中的任意两个元素都连通。
并查集有个非常重要的一步就是数组初始化
void init() {
//表示每个点就是一棵只有一个结点的树
int i;
for (i = 1; i <= n; i++) {
f[i] = i;
}
return;
}
然后再根据所给信息将这些树合并成一棵大树
int main(void) {
int i, x, y;
scanf("%d %d", &n, &m);
init();
for (i = 1; i <= m; i++) {
scanf("%d %d", &x, &y);//输入连通边
merge(x, y);
}
for (i = 1; i <= n; i++) {
if (f[i] == i)
sum++;
}
printf("%d\n", sum);//sum表示不同的集合的个数
return 0;
}
void merge(int v, int u) {
int t1, t2;//用t1,t2来表示v,u的祖先
t1 = getf(v);
t2 = getf

最低0.47元/天 解锁文章
1006





