并查集 Love The Way You Lie 2022-04-17 02:27 379阅读 0赞 ### 森林: ### 森林是由若干棵互不相交的树组成,两棵树分别独立,没有交集 ![20181112082744488.png][] ### 并查集: ### 并查集的结构和森林十分相似,是用于解决不相交集合如下若干几种操作的统称 ### 1.MAKE\_SET(x):初始化操作,建立一个只包含元素x的集合 ### ### 2.UNION(x,y):合并操作,将包含x和y的集合合并成一个新集合 ### ### 3.FIND\_SET(x):查询操作,计算x所在集合 ### (一般用于求不相交集合的并集) 通常我们用有根树来表示集合,树中的每个结点对应集合中的一个成员 每个成员有一条指向父节点的边,整个有根树通过这些指向父节点的边来维护 **每棵树的根就是这个集合的代表,并且这个代表的父节点就是它自己** ### 基本操作: ### 初始化: 对每个元素都建立一个只包含该元素自己的集合,这意味着每个成员都是自身所在集合的代表,只需将父节点设为它自己 查询: 在不相交的森林中,并查集的查询操作,指的是查出指定元素所在有根树的根节点是谁 合并: 查找到代表元素,将其中一个根节点的父亲设置成另外一个根节点,如下图演示,我们完成了合并操作 ![20181112084256857.png][] 集合的传递性(如果a和b同属一个集合,b和c同属一个集合,那么a和c也同属一个集合) ### 相应算法的实现: ### 创建一个并查集: class DDJSSet { private: int* father; //用来保存每个结点的父结点 int* rank; //用来保存每个结点的秩 public: DDJSSet(int size) { father = new int[size]; rank = new int[size]; for (int i = 0; i < size; ++i) { father[i] = i; //初始化时,将每个结点的父节点指向它自己 rank[i] = 0; } } ~DDJSSet() { delete[] father; delete[] rank; } }; 查询操作: 1.寻找当前结点的父结点 2.如果父节点是它本身,那么该点就是父节点,如果不是,则返回步骤1继续查找 合并操作: 1.分别获得传入的两个结点所在树的根结点 2.如果两个数所在根节点相同,说明他们在同一棵树上,返回false,结束合并操作 3,如果两个根节点不同,则将一个根节点的父节点指向另一个根节点,返回true结束操作 但是这样做会带来一些问题:我们任选一个结点指向一棵树的父结点,可能会导致一子棵树过长,最终整个并查集退化成一个链表,降低了查找效率,我们可以通过树的高度来判断连接顺序,将高度低的树的根节点连接到高度高的树的根节点 按秩合并: 1.利用一个数组保存每个结点所在树的高度的(初始化为0) 2.获得传入结点的树的根节点 3.若两个根节点不同,比较他们的高度 4.将高度低的树的父节点指向高度高的树的根结点 5.更新合并后的根节点的高度,返回 /*合并操作*/ bool merge(int node1, int node2) { int ancestor1 = find_set(node1); int ancestor2 = find_set(node2); if (ancestor1 != ancestor2) { if (rank[ancestor1] > rank[ancestor2]) { swap(ancestor1, ancestor2); } father[ancestor1] = ancestor2; rank[ancestor2] = max(rank[ancestor2], rank[ancestor1] + 1); //更新秩 return true; } return false; } ### 路径压缩: ### ![20181112092153616.png][] 如上图所示,如果我们把每一个子节点都指向这个并查集的根节点,这样会大大地降低查找效率 在执行寻找根节点的函数中,我们稍作修改,将查找路径上的所有结点都指向最终查找到的根节点 /*路径压缩算法*/ int find_set(int node) { if (father[node] != node) { father[node] = find_set(father[node]); } return father[node]; } ### 整体代码: ### #include <iostream> #include <algorithm> using namespace std; class zDisjointSet { private: int* father; int* rank; public: zDisjointSet(int size) { father = new int[size]; rank = new int[size]; for (int i = 0; i < size; ++i) { father[i] = i; rank[i] = 0; } } ~zDisjointSet() { delete[] father; delete[] rank; } /*路径压缩算法*/ int find_set(int node) { if (father[node] != node) { father[node] = find_set(father[node]); } return father[node]; } /*合并操作*/ bool merge(int node1, int node2) { int ancestor1 = find_set(node1); int ancestor2 = find_set(node2); if (ancestor1 != ancestor2) { if (rank[ancestor1] > rank[ancestor2]) { swap(ancestor1, ancestor2); } father[ancestor1] = ancestor2; rank[ancestor2] = max(rank[ancestor2], rank[ancestor1] + 1); //更新秩 return true; } return false; } }; ### ### [20181112082744488.png]: /images/20220417/d70be596421a4b568afd6e9725214a28.png [20181112084256857.png]: /images/20220417/b44ac4ba51d649ecabd183c2e3e08ceb.png [20181112092153616.png]: /images/20220417/f6818ee84d424352b465bfc053c318b1.png
相关 并查集 Ⅱ \[poj 1611\] ([http://poj.org/problem?id=1611][http_poj.org_problem_id_1611]) 题目描述: T 古城微笑少年丶/ 2022年08月03日 14:35/ 0 赞/ 291 阅读
相关 并查集 并查集JAVA版框架 并查集是一种用来管理元素分组情况的数据结构。 并查集可以高效地进行如下操作: \--查询元素a和元素b是否属于同一组 落日映苍穹つ/ 2022年06月16日 12:44/ 0 赞/ 329 阅读
相关 并查集 这个文章是几年前水acm的时候转的, 当时也不知道作者是谁, 要是有人知道的话说一下吧 并查集是我暑假从高手那里学到的一招,觉得真是太精妙的设计了。以前我无法解决的 港控/mmm°/ 2022年06月13日 14:13/ 0 赞/ 311 阅读
相关 并查集 > 题目 > 某学校近期要组织全校同学出去参加某项活动,由于人数众多,学校决定让同学们自行组队,以小组为单位进行活动。假设学校一共n个同学,每个同学有一个唯一的数字作为标签 Myth丶恋晨/ 2022年06月08日 09:24/ 0 赞/ 321 阅读
相关 并查集 森林: 森林是由若干棵互不相交的树组成,两棵树分别独立,没有交集 ![20181112082744488.png][] 并查集: 并查集的结构和森林十分相似,是 Love The Way You Lie/ 2022年04月17日 02:27/ 0 赞/ 380 阅读
相关 并查集 来看一个实例,[杭电1232畅通工程][1232] 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性 我就是我/ 2022年03月29日 10:58/ 0 赞/ 384 阅读
相关 并查集 > 并查集是一种树形的数据结构,用于集合的合并。 与C++STL相比的优势: 1. 可以同时维护多个集合 2. 快速的合并两个集合 \\现实: 用数组实现。fat 左手的ㄟ右手/ 2022年02月05日 00:23/ 0 赞/ 272 阅读
相关 并查集 例题: ![输入样例][20190805122001677.png] 输入样例,第一行为一个整数n,代表有n台电脑,编号1-n;接下来进行一系列操作,当输入‘c’时,判 Dear 丶/ 2021年11月11日 08:04/ 0 赞/ 395 阅读
相关 并查集 一、算法解释 用于解决一些有N个元素的集合应用问题。 1、将每个元素初始化为自身单独成为一个集合。用p\[i\]的值表示该元素所在集合。 ![这里写图片描述][S 桃扇骨/ 2021年09月14日 02:56/ 0 赞/ 488 阅读
相关 并查集 并查集的作用就是快速判断两个元素是否在同一个集合中,快速将两个集合合并 基本模板 include <iostream> include <a 比眉伴天荒/ 2021年06月22日 15:37/ 0 赞/ 588 阅读
还没有评论,来说两句吧...