并查集(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. 从安装 centos 到运行 laravel 的配置

    # 安装 centos cd /etc/sysconfig/network-scripts/ vi ifcfg-xxx # 修改 ONBOOT="no" 为 "yes&q ...

  2. [转]为什么要引入nullptr?

    来源:https://cloud.tencent.com/developer/ask/69685 C++11介绍nullptr,它被称为Null指针常数及其提高类型安全性和解决不明确的情况与现有实现相 ...

  3. Linux日常之命令sed

    一. 命令sed简介 利用命令sed能够同时处理多个文件多行的内容,可以不对原文件改动,仅把匹配的内容显示在屏幕上,也可以对原文件进行改动,但是不会在屏幕上返回结果,若想查看改动后的文件,可以使用命令 ...

  4. 最简洁地说明常用的git指令(1)

    前提条件,在github上面创建一个仓库,注册好git账号,下面开始 首先在项目文件夹下面,如果有安装git则邮件gitbash进入控制台.另一种方式是使用IDEA打开你要上传的工程,在里面的命令行下 ...

  5. putty ssh常用命令小结

    打开putty 输入VPS的IP地址输入root回车输入密码回车 vps 更改文件夹所属组 cd /home/vpsuser/domains/afish.cnblogs.com/ chown -R v ...

  6. PS使用滤镜制作光晕效果

    滤镜制作光晕效果 新建图层,将背景色填充为黑色 滤镜->渲染->镜头光晕 调整好光晕大小 通过滤色(图层两字下面一点点的位置,有个下拉菜单,点开就在里面),去黑留白 如果觉得光线不够,可以 ...

  7. C++ fstream 用法

    #include <fstream> #include <iostream> main() { int a,b,c,d; std::ifstream infile (" ...

  8. WIN 7 的vs2008 试用版评估期结束的解决方法

    1. 在VS2008安装目录下把Setup/setup.sdb文件中的 [Product Key] T2CRQGDKBVW7KJR8C6CKXMW3D 改成 [Product Key] PYHYPWX ...

  9. Linux入门培训教程 常见linux命令释义

    快到中午吃饭了,然后忽然想起来samba里面没有添加用户.于是乎,就玩弄起了samba. Samba三下五除二就安装好了,想想window里面不断的点击下一步,还要小心提防各种隐藏再角落里的绑定软件. ...

  10. codevs 5935 小球 x

    题目描述 Description 许多的小球一个一个的从一棵满二叉树上掉下来组成FBT(Full Binary Tree,满二叉树),每一时间,一个正在下降的球第一个访问的是非叶子节点.然后继续下降时 ...