并查集(Union Find Set)

这篇文章我们来讲一下并查集,什么是并查集呢?来举一个形象的例子。

话说符文之地上居住着各式各样的英雄,他们效忠于自己的国家或部落,整天背着武器在外面执行任务,碰到和自己不是一队的,就免不了要打一架。英雄们都有一个优点就是讲义气,绝对不打自己的队友,而且他们信奉“队友的队友就是我的队友”,只要是能通过队友关系串联起来的,不管拐了多少个弯,都认为是自己人。这样一来,不在同一个阵营的人,无论如何都无法通过队友关系连起来,就可以放心往死里打了。
两个原本互不相识的人,怎么判断是否属于一个阵营呢?我们可以在每个阵营内推举出一个比较有名望的人,作为该阵营的代表人物。比如德玛西亚的君主虽然是选举出来的,但每一代的嘉文都能成功登上王位。现任君主是嘉文三世,他的儿子基本可以确定是下一代君主。这样,每个阵营都有了自己的领军人物,或者叫队长,两人开打之前,只要互相确认一下自己的队长是不是同一个人,就可以确定敌友关系了。

还有一个问题啊,英雄们只知道自己直接的队友是谁,很多人压根就不认识队长,要判断自己的队长是谁,只能漫无目的的通过队友的队友关系问下去:“你是不是队长?你是不是队长?”这样一来,队长面子上挂不住了,而且效率太低,还有可能陷入无限循环中。于是队长下令,重新组队,队内所有人实行分等级制度,形成树状结构,队长就是根节点,下面分别是二级队员、三级队员,每个人只要记住自己的上级是谁就行了。遇到判断敌友的时候,只要一层层向上问,直到最高层,就可以在短时间内确定队长是谁了。

int setSize = 0;
unordered_map<int, int> father;
int find(int x) {int root = x;while (this->father[root] != -1) {root = this->father[root];}return root;
}

有一天,远在地球的孙悟空,发现了能量波动的符文大陆,于是分身来到了这里,这对于符文大陆来说,孙悟空属于新来的英雄,不属于任何阵营,那么它的上级就是它自己。我们定义一个add函数,参数x表示新英雄的ID,首先得确保这个ID不在原来的任何一个阵营里,然后把它的上级设置成-1表示它就是队长,最后让阵营的数量+1。

void add(int x) {if (!this->father.count(x)) {this->father[x] = -1;this->setSize++;}
}

孙悟空来到符文大陆之后,由于旅途的奔波,让大圣不负原来世界的威能,经过猴子长者的指导,去北方寻找猴群,偶遇易大师,拜于无极剑道。易大师后来带猴子去阿狸的包子铺吃包子,阿狸见猴子无家可归,很可怜,就收留了猴子,这两个动物日久生情,成为了跨越种族的情侣。
九尾妖狐阿狸是属于艾欧尼亚阵营的,猴子也就顺理成章的加入了艾欧尼亚(找了个有户口的女人),怎么加入呢?

bool merge(int x, int y) {int rootX = this->find(x);int rootY = this->find(y);if (rootX != rootY) {father[rootX] = rootY;this->setSize--;}
}

我们把猴子的ID-x和阿狸的ID-y都传进merge函数中,然后通过find函数分别找到x和y的根节点,如果rootX != rootY,说明两个节点不是属于一个阵营的,我们把father[rootX] = rootY,这样就相当于把x加入到了y的阵营,最后让阵营的数量-1。

有一天,猴子出去执行任务,正好遇到了岩雀塔莉垭,但他俩互相不认识,不知道能不能动手,就开始找自己的上头问,猴子就去问自己的师傅无极剑圣——易大师,认不认识一个在石头上滑滑板的小孩,岩雀也去问自己的师傅疾风剑豪——亚索,认不认识一只拿着棒子的猴子。剑圣表示不认识啊,我去问问艾欧尼亚的领袖卡尔玛,亚索也表示,不知道什么猴子,也得去问问卡尔玛。一路问上去,最后才确定,两个人都是艾欧尼亚的。

这样一连串的问太麻烦了,怎么办呢,干脆把所有的队员都直接挂在队长的旗下,出了事直接问队长,这样效率也高,所以我们得把整个阵营的层数维持在较低的水平上,也就是路径压缩算法。

int find(int x) {int root = x;while (this->father[root] != -1) {root = this->father[root];}while (x != root) {int original = this->father[x];this->father[x] = root;x = original;}return root;
}

算法模板

class UnionFindSet{private:int setSize = 0;unordered_map<int, int> father;public:int find(int x) {int root = x;while (this->father[root] != -1) {root = this->father[root];}while (x != root) {int original = this->father[x];this->father[x] = root;x = original;}return root;}bool isUnion(int x, int y) {return this->find(x) == this->find(y);}void merge(int x, int y) {int rootX = this->find(x);int rootY = this->find(y);if (rootX != rootY) {father[rootX] = rootY;this->setSize--;}}void add(int x) {if (!this->father.count(x)) {this->father[x] = -1;this->setSize++;}}
};

应用

  1. 检查 graph 中是否存在环

并查集(Union Find Set)相关推荐

  1. 数据结构-PHP 并查集(Union Find)

    文章目录 数据结构-PHP 并查集(Union Find) 1.并查集示意图 2.并查集合并 3.并查集简单的代码示例 3.1 PHP代码定义 3.2 输出演示 数据结构-PHP 并查集(Union ...

  2. 关于 并查集(union find) 算法基本原理 以及 其 在分布式图场景的应用

    二月的最后一篇水文-想写一些有意思的东西. 文章目录 环检测在图数据结构中的应用 深度/广度优先 检测环 并查集数据结构 (Union-Find) 基本概念 初始化 合并 union 查找祖先 优化1 ...

  3. 数据结构与算法(十二)并查集(Union Find)及时间复杂度分析

    本文主要包括以下内容: 并查集的概念 并查集的操作 并查集的实现和优化 Quick Find Quick Union 基于size的优化 基于rank的优化 路径压缩优化 并查集的时间复杂度 并查集的 ...

  4. Kruskal算法与并查集

    Kruskal算法与并查集 一.Kruskal算法 1. 概念 Kruskal算法就是按照图中各个边上的权值大小进行递增排序,以此来构造最小生成树. 2.重点解析 在由Kruskal实现最小生成树的过 ...

  5. vb6实现union数据结构_数据结构与算法——并查集(不相交集合)

    首发公众号:bigsai 认识并查集 对于并查集(不相交集合),很多人会感到很陌生,没听过或者不是特别了解.实际上并查集是一种挺高效的数据结构.实现简单,只是所有元素统一遵从一个规律所以让办事情的效率 ...

  6. C++用并查集Disjoint union实现connected component连通分量(附完整源码)

    C++用并查集Disjoint union实现connected component连通分量 C++用并查集Disjoint union实现connected component连通分量完整源码(定义 ...

  7. 【并查集】Union Find

    并查集 引出并查集 并查集(Union Find) 如何存储数据? 接口定义 元素的初始化 UnionFind.java Quick Find union 示例及实现 find 实现 Quick Fi ...

  8. 第三十一篇 玩转数据结构——并查集(Union Find)

    1.. 并查集的应用场景 查看"网络"中节点的连接状态,这里的网络是广义上的网络 数学中的集合类的实现 2.. 并查集所支持的操作 对于一组数据,并查集主要支持两种操作:合并两个数 ...

  9. Codeforces 并查集题集(Disjoint Sets Union Step1)

    ITMO Academy: pilot course Disjoint Sets Union Step1 A. Disjoint Sets Union 思路:并查集模板111 Code: #inclu ...

最新文章

  1. Quart 2D 绘制图形简单总结
  2. PingingLab传世经典系列《CCNA完全配置宝典》-2.5 RIPv2基本配置
  3. 百融金服榕树_百融金服榕树成为拉动新金融行业增长的主力军
  4. win10计算机拒绝访问,教你win10系统c盘拒绝访问怎么办
  5. 想避免宕机,数据中心运营商还要不断演练实践
  6. 在python中使用sort_Python中的sort()方法使用基础教程
  7. Python初学者选择集成开发环境的原则!可以从以下几个方面着手
  8. QDoc文字标记textmarkup
  9. GARFIELD@01-19-2005
  10. 数字图像处理 空间域锐化 MATLAB实验
  11. 使用ExcelPythonHiveSparkSQL进行数据分析开篇-环境搭建攻略!
  12. 冒泡排序(bubble sort)算法实现
  13. SSM(SpringBoot+SpringMVC+Mybatis):班委信息管理附有GIF动图,博主可免费答疑
  14. Easyui 默认图标以及自定义图标
  15. android模拟器root权限获取,如何在Android模拟器上获得root访问权限?
  16. 火箭十八连胜内幕大曝光(坚持看完)(搞笑)
  17. QQ快速登录协议分析以及风险反思
  18. python制作折线图_python 生成折线图
  19. appinventor网络编程php,AppInventor离线版下载
  20. VC调试器高级应用(转)

热门文章

  1. WPF 使用MahApps.Metro UI库
  2. 【转】微服务实践(五):微服务的事件驱动数据管理
  3. ActionBarSherlock ViewPagerIndicator
  4. [Linux命令]Sed命令参数
  5. Java黑皮书课后题第5章:*5.46(倒排一个字符串)编写一个程序,提示用户输入一个字符串,然后以反序显示该字符串
  6. Java黑皮书课后题第2章:2.18(打印表格)编写程序,显示下面的表格,将浮点数值类型转化为整数
  7. html如何将标题置顶,.Html 头部,标题
  8. 《构架之美》阅读笔记三
  9. Halcon - 测量 - 轮廓到线的距离
  10. js -- 移动端pc端自动切换