并查集(Union Find Set)
并查集(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++;}}
};
应用
- 检查 graph 中是否存在环
并查集(Union Find Set)相关推荐
- 数据结构-PHP 并查集(Union Find)
文章目录 数据结构-PHP 并查集(Union Find) 1.并查集示意图 2.并查集合并 3.并查集简单的代码示例 3.1 PHP代码定义 3.2 输出演示 数据结构-PHP 并查集(Union ...
- 关于 并查集(union find) 算法基本原理 以及 其 在分布式图场景的应用
二月的最后一篇水文-想写一些有意思的东西. 文章目录 环检测在图数据结构中的应用 深度/广度优先 检测环 并查集数据结构 (Union-Find) 基本概念 初始化 合并 union 查找祖先 优化1 ...
- 数据结构与算法(十二)并查集(Union Find)及时间复杂度分析
本文主要包括以下内容: 并查集的概念 并查集的操作 并查集的实现和优化 Quick Find Quick Union 基于size的优化 基于rank的优化 路径压缩优化 并查集的时间复杂度 并查集的 ...
- Kruskal算法与并查集
Kruskal算法与并查集 一.Kruskal算法 1. 概念 Kruskal算法就是按照图中各个边上的权值大小进行递增排序,以此来构造最小生成树. 2.重点解析 在由Kruskal实现最小生成树的过 ...
- vb6实现union数据结构_数据结构与算法——并查集(不相交集合)
首发公众号:bigsai 认识并查集 对于并查集(不相交集合),很多人会感到很陌生,没听过或者不是特别了解.实际上并查集是一种挺高效的数据结构.实现简单,只是所有元素统一遵从一个规律所以让办事情的效率 ...
- C++用并查集Disjoint union实现connected component连通分量(附完整源码)
C++用并查集Disjoint union实现connected component连通分量 C++用并查集Disjoint union实现connected component连通分量完整源码(定义 ...
- 【并查集】Union Find
并查集 引出并查集 并查集(Union Find) 如何存储数据? 接口定义 元素的初始化 UnionFind.java Quick Find union 示例及实现 find 实现 Quick Fi ...
- 第三十一篇 玩转数据结构——并查集(Union Find)
1.. 并查集的应用场景 查看"网络"中节点的连接状态,这里的网络是广义上的网络 数学中的集合类的实现 2.. 并查集所支持的操作 对于一组数据,并查集主要支持两种操作:合并两个数 ...
- Codeforces 并查集题集(Disjoint Sets Union Step1)
ITMO Academy: pilot course Disjoint Sets Union Step1 A. Disjoint Sets Union 思路:并查集模板111 Code: #inclu ...
最新文章
- Quart 2D 绘制图形简单总结
- PingingLab传世经典系列《CCNA完全配置宝典》-2.5 RIPv2基本配置
- 百融金服榕树_百融金服榕树成为拉动新金融行业增长的主力军
- win10计算机拒绝访问,教你win10系统c盘拒绝访问怎么办
- 想避免宕机,数据中心运营商还要不断演练实践
- 在python中使用sort_Python中的sort()方法使用基础教程
- Python初学者选择集成开发环境的原则!可以从以下几个方面着手
- QDoc文字标记textmarkup
- GARFIELD@01-19-2005
- 数字图像处理 空间域锐化 MATLAB实验
- 使用ExcelPythonHiveSparkSQL进行数据分析开篇-环境搭建攻略!
- 冒泡排序(bubble sort)算法实现
- SSM(SpringBoot+SpringMVC+Mybatis):班委信息管理附有GIF动图,博主可免费答疑
- Easyui 默认图标以及自定义图标
- android模拟器root权限获取,如何在Android模拟器上获得root访问权限?
- 火箭十八连胜内幕大曝光(坚持看完)(搞笑)
- QQ快速登录协议分析以及风险反思
- python制作折线图_python 生成折线图
- appinventor网络编程php,AppInventor离线版下载
- VC调试器高级应用(转)
热门文章
- WPF 使用MahApps.Metro UI库
- 【转】微服务实践(五):微服务的事件驱动数据管理
- ActionBarSherlock ViewPagerIndicator
- [Linux命令]Sed命令参数
- Java黑皮书课后题第5章:*5.46(倒排一个字符串)编写一个程序,提示用户输入一个字符串,然后以反序显示该字符串
- Java黑皮书课后题第2章:2.18(打印表格)编写程序,显示下面的表格,将浮点数值类型转化为整数
- html如何将标题置顶,.Html 头部,标题
- 《构架之美》阅读笔记三
- Halcon - 测量 - 轮廓到线的距离
- js -- 移动端pc端自动切换