并查集(Disjoint Set)用来判断已有的数据是否构成环。

在构造图的最小生成树(Minimum Spanning Tree)时,如果采用 Kruskal 算法,每次添加最短路径前,需要先用并查集来判断一下这个路径是否会构成环。

思路

遍历图的每一条边,按照下面的原则将对应的两个顶点添加到集合中:

  • 如果两个顶点都不属于任一集合,则创建新的集合,并将这两个顶点放入
  • 如果两个顶点都已经属于某个集合,则已经构成环,退出
  • 如果有一个顶点已经属于某个集合,则将另一个顶点也加入这个集合

为了代码上的统一性,可以在开始前,把所有顶点都看成只有一个元素的集合,然后就是不停的合并集合。

集合可以用树的双亲表示法来表示,只需要额外创建一个数组即可。为了简化合并操作,可以每次都只操作两颗树的根结点。

int parent[n];

// 查找树的根结点
int findRoot(int parent[], int key) {
int root = key;
while (parent[root] != -1) {
root = parent[root];
}
return root;
}
// 合并树
int unionVertex(int parent[], int x, int y) {
int lRoot = findRoot(parent, x);
int rRoot = findRoot(parent, y);
// 两个结点的根结点为同一个,则这两个结点属于同一棵树
if (lRoot == rRoot) {
return 0;
}
// 否则,合并树,这里直接把左树作为右树的子树,可能会导致不平衡
parent[lRoot] = rRoot;
}

代码

为了在每次合并时,尽可能保证树的平衡,再创建一个数组保存树的高度,合并时将高度低的树作为子树即可。

#include <stdio.h>

void init(int parent[], int height[], int count) {
int i;
for (i = 0; i < count; i++) {
parent[i] = -1;
height[i] = 0;
}
} int findRoot(int parent[], int key) {
int root = key;
while (parent[root] != -1) {
root = parent[root];
}
return root;
} int unionVertex(int parent[], int height[], int x, int y) {
int lRoot = findRoot(parent, x);
int rRoot = findRoot(parent, y);
if (lRoot == rRoot) {
return 0;
}
// parent[lRoot] = rRoot;
if (height[lRoot] < height[rRoot]) {
parent[lRoot] = rRoot;
} else if (height[rRoot] < height[lRoot]) {
parent[rRoot] = lRoot;
} else {
parent[lRoot] = rRoot;
height[rRoot]++;
}
return 1;
} int main(void) {
int edgeCount = 6, vertexCount = 5;
int i;
// 图中的边
int graph[5][2] = {
{0, 1}, {2, 4}, {1, 2}, {1, 3},
{2, 5}
};
int parent[edgeCount];
int height[edgeCount]; init(parent, height, edgeCount); for (i = 0; i < vertexCount; i++) {
int ret = unionVertex(parent, height, graph[i][0], graph[i][1]);
if (ret == 0) {
printf("%d, %d\n", graph[i][0], graph[i][1]);
printf("find cycle!\n");
return 0;
}
} printf("no find cycle!\n");
for (i = 0; i < vertexCount; i++) {
printf("%d's parent is: %d\n", i, parent[i]);
}
for (i = 0; i < vertexCount; i++) {
printf("%d's height is: %d\n", i, height[i]);
} return 0;
}

执行结果:

no find cycle!
0's parent is: 1
1's parent is: 4
2's parent is: 4
3's parent is: 4
4's parent is: -1
0's height is: 0
1's height is: 1
2's height is: 0
3's height is: 0
4's height is: 2

【算法与数据结构】并查集 Disjoint Set的更多相关文章

  1. 算法手记 之 数据结构(并查集详解)(POJ1703)

    <ACM/ICPC算法训练教程>读书笔记-这一次补上并查集的部分.将对并查集的思想进行详细阐述,并附上本人AC掉POJ1703的Code. 在一些有N个元素的集合应用问题中,通常会将每个元 ...

  2. ACM数据结构-并查集

    ACM数据结构-并查集   并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合 ...

  3. 【算法导论-36】并查集(Disjoint Set)具体解释

    WiKi Disjoint是"不相交"的意思.Disjoint Set高效地支持集合的合并(Union)和集合内元素的查找(Find)两种操作,所以Disjoint Set中文翻译 ...

  4. 【数据结构】【计算机视觉】并查集(disjoint set)结构介绍

    1.简述 在实现多图像无序输入的拼接中,我们先使用surf算法对任意两幅图像进行特征点匹配,每对图像的匹配都有一个置信度confidence参数,来衡量两幅图匹配的可信度,当confidence> ...

  5. 并查集(Disjoint Set)

    在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中.这一类问题其特点是看似并不复杂, ...

  6. POJ 2421 Constructing Roads (Kruskal算法+压缩路径并查集 )

    Constructing Roads Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19884   Accepted: 83 ...

  7. hdu 4641 K-string SAM的O(n^2)算法 以及 SAM+并查集优化

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4641 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末 ...

  8. hdu 1233(还是畅通project)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)

    还是畅通project Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  9. hdu 4641K-string SAM的O(n^2)算法 以及 SAM+并查集优化

    转载:http://www.cnblogs.com/hxer/p/5675149.html 题意:有一个长度为n(n < 5e4)的字符串,Q(Q<=2e5)次操作:操作分为:在末尾插入一 ...

随机推荐

  1. adb shell命令模拟按键/输入input使用keycode 列表详解

    在adb shell里有一个非常使用的命令,模拟按键输入,这里首先不要理解为是键盘的模拟按键,下面命令的使用和键值做一个详解. input命令格式 adb shell input keyevent & ...

  2. Big Data(八)MapReduce的搭建和初步使用

    ---恢复内容开始--- 回顾: 1.最终开发MR的计算程序 2.hadoop 2.x 出现了一个yarn:资源管理>>MR没有后台场服务 yarn模型:container 容器,里面会运 ...

  3. BZOJ 4999 LCA树状数组差分维护DFS序

    Description 给一颗树,每个节点有个初始值 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x 2. Q i j x(0<=x<2 ...

  4. java数据结构3--List

    List 1.1 list接口的简介 1.2 list实现子类 ArrayList:线程不安全,查询速度快,底层用的是数组,增删慢LinkedList:线程不安全,链表结构,增删速度快,查询慢Vect ...

  5. Spring IOC(一)

    最近复习,准备整理下复习笔记 Spring IOC 部分: 控制反转(Inversion of Control) IOC是什么 简言之 IOC完成的事情原先由程序员主动通过new实例化对象事情,转交给 ...

  6. Scala传递参数遇到的坑

    1.方法中的参数全为val型. 例: def insertMap(map:=>Map[String,Int]):Unit={ map+=("b"->2)    //报错 ...

  7. xgboost使用细节

    from http://blog.csdn.net/zc02051126/article/details/46771793 在Python中使用XGBoost 下面将介绍XGBoost的Python模 ...

  8. layui静态表格固定td宽度,table固定td宽度

    正在做一个项目,要求数据表的列是不固定的,有可能是有10列,有可能是20列,第一列宽度要固定,然后我怎么设置都没有用, 这个问题困扰了我三天,后来终于百度到了, 这个博客: https://www.c ...

  9. 【leetcode】1228.Missing Number In Arithmetic Progression

    题目如下: 解题思路:题目很简单.先对数组排序,根据最大值和最小值即可求出公差,然后遍历数组,计算相邻元素的差,如果差不等于公差,即表示数字缺失. 代码如下: class Solution(objec ...

  10. msyql 优化之五不要

    1.尽量不要有空判断的语句,因为空判断将导致全表扫描,而不是索引扫描. 对于空判断这种情况,可以考虑对这个列创建数据库默认值 //空判断将导致全表扫描 select small_id from sma ...