并查集(加权规则、折叠规则)
1.基本知识概念
等价类与并查集。如果用符号“=”表示集合上的等价关系,那么对于该集合中的任意对象x,y,z,下列性质成立 :
自反性:x=x(即等于自身)
对称性:若x=y,则y=x
传递性:若x=y且y=z,则x=z
一个集合S中的所有对象可以通过等价关系划分为若干个互不相交的子集S1,S2,S3,…,它们的并集就是S,这些子集即为等价类。
确定等价类的方法:
第一步:读入并储存所有的等价对(i,j);
第二步:标记和输出所有的等价类。
2.解决步骤分析:
假定给定集合:S={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
及以下等价对:
①0=4
②3=1
③6=10
④8=9
⑤7=4
⑥6=8
⑦3=5
⑧2=11
⑨11=0
我们以等式左边的值为根,最后一棵树是一个等价类,如果两个结点的根节点相同,就是在一个等价类。
如下解决过程:
如下图,黑色的为单个等价类,其他颜色相同的为一个等价类,我们以等号左边的作为根:
处理完⑤-⑧后的结果 :
处理完⑨后的结果 :
3.解决代码:
3.1正常普通解决代码:
class UFsets
{private:int* parent;unsigned int size;
public:UFsets(unsigned int sz){size = sz;parent = (int*)malloc(sizeof(int) * sz);for (int i = 0; i < size; i++){parent[i] = -1;}}~UFsets(){free(parent);}bool Union(int a, int b){bool res = false;int ra = FindParent(a);int rb = FindParent(b);if (ra != rb){parent[ra] += parent[rb];parent[rb] = ra;res = true;}return res;}int FindParent(int ra){while (parent[ra] >= 0){ra = parent[ra];}return ra;}void Print(int ri){printf("%3d ", ri);for (int i = 0; i < size; i++){if (parent[i] == ri){Print(i);}}}void PrintSet(){int s = 0;for (int i = 0; i < size; i++){if (parent[i] < 0){printf("第 %d 集合\n", ++s);Print(i);printf("\n");}}}
};int main()
{UFsets set(12);set.Union(0, 4);set.Union(3, 1);set.Union(6, 10);set.Union(8, 9);set.Union(7, 4);set.Union(6, 8);set.Union(3, 5);set.Union(2, 11);set.Union(11, 0);return 0;
}
调试查看parent值发现和我们分析时最后的数组结果一样(我统一以等价左边的值作为根):
用类的PrintSet()打印各个等价类结果:
4.加权规则和折叠规则
但是Find和Union的操作性能不好。假设最初n个元素构成n棵树组成的森林,parent[i] = -1。做处理Union(n-2,n-1),Union(n-3,n-1),Union(n-4,n-1)…Union(0,n-1)后,将产生如下图所示的退化的树:
执行一次Union操作需时间O(1),n-1此是O(n)。若再执行Find(0),Find(1),…,Find(n-1),若被搜索的元素为i,完成Find(i)操作为O(i),完成n次搜索是O(n^2)。
所以在这里提出了加权规则和折叠规则。
4.1加权规则
先判断两个集合中的结点个数,如果以i为根的树中的结点个数少于以j为根的树中的结点个数,即parent[i] > parent[j],则让j成为i的双亲,否则,让i成为j的双亲。以下即为加权规则代码吗,将以下代码添加到class UFsets中即可。
bool WeightedUnion(int a, int b)//加权规则{bool res = false;int ra = FindParent(a);int rb = FindParent(b);if (ra != rb){if (parent[ra] > parent[rb])//说明parent[rb]结点更多,让rb成为根节点{parent[rb] += parent[ra];parent[ra] = rb;}else//让ra成为根节点{parent[ra] += parent[rb];parent[rb] = ra;}res = true;}return res;}
4.2折叠规则
如果j是从i到根的路径上的一个结点,并且parent[j] ≠ root,则把parent[i]置于root,意思是让i的双亲直接为root。
如下即为从i结点向上压缩路径,将代码添加到class UFsets中即可 :
//折叠规则压缩路径void Coollapsingfind(int i){int j = i;while (parent[j] >= 0)//寻找树的根节点{j = parent[j];}while (i != j){int tmp = parent[i];parent[i] = j;i = tmp;}}
以下为折叠压缩后的结果:
并查集(加权规则、折叠规则)相关推荐
- Rochambeau POJ - 2912 (枚举和加权并查集+路径压缩)找唯一裁判
题意:有n个人玩石头剪刀布,有且只有一个裁判.除了裁判每个人的出拳形式都是一样的. a<b表示b打败a,a=b表示a和b出拳一样,平手.a>b表示a打败b. 给出m个回合的游戏结果,问能否 ...
- hdu 3635 Dragon Balls(加权并查集)2010 ACM-ICPC Multi-University Training Contest(19)
这道题说,在很久很久以前,有一个故事.故事的名字叫龙珠.后来,龙珠不知道出了什么问题,从7个变成了n个. 在悟空所在的国家里有n个城市,每个城市有1个龙珠,第i个城市有第i个龙珠. 然后,每经过一段时 ...
- 拼多多关键词的排名是怎么查?拼多多排名规则
拼多多产品的标题,关键词非常重要,现在企业需要每天找到好的关键词或比较同行关键词,知道一般排名,大类别和小类别关键词不同,客户搜索商品关键词惯性,是企业需要了解,好的关键词可以给商店带来好的流量,所以 ...
- 快手集福气中国牛 2021快手集福卡活动规则
快手集福气中国牛,集福卡活动规则 一.活动时间 2021年1月29日00:00 至2021年2月10日23:59 二.活动玩法 1.福卡介绍 福卡分为两种,即福气卡与福牛卡,每种卡均有五种字符卡片如下 ...
- A Bug‘s Life POJ 2492 加权并查集
A Bug's Life POJ 2492 加权并查集 传送门:http://poj.org/problem?id=2492 Description Background Professor Hopp ...
- poj1182(加权值的并查集)
Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它 ...
- 【加权并查集】bzoj 4602 齿轮
立志用最少的代码做最高效的表达 Description 现有一个传动系统,包含了N个组合齿轮和M个链条.每一个链条连接了两个组合齿轮u和v,并提供了一个传动比x : y.即如果只考虑这两个组合齿轮,编 ...
- Zjnu Stadium HDU - 304 加权并查集
题意: 观众席围成一圈.列的总数是300,编号为1–300,顺时针计数,我们假设行的数量是无限的.将有N个人去那里.他对这些座位提出了要求:这意味着编号A的顺时针X距离坐着编号B.例如:A在第4列,X ...
- 数据结构 之 并查集
并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题. 有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构 ...
最新文章
- 炸裂!MySQL 82 张图带你飞!
- TeskLink—增加一种需求类型(业务流程)(version1.9.8)
- Google App Engine技术架构之Google App Engine的简介
- android base64解密,android Base64 AES加密解密
- [move_base-24] process has died [exit code -6, cmd lib/move_base/move_base odom:=mobile_base_control
- httpclient 学习
- MyEclipse2015修改项目部署名称(WebContextRoot)
- 一、Web服务器——Tomcat Servlet学习笔记
- 如何查看mysql8.0的默认密码_MySQL8.0安装之后查找默认密码
- IndexError:boolean index did not match indexed array along dimension 0
- python123用户登录的三次机会_用户登录三次机会(PYTHON)
- 2021-02-23 天地图图层类型总结
- 如何才能让项目团队高效稳定?
- java 字符串去重排序
- 解决 macOS Big Sur 新安装ideaIU-2021.2.2 无法启动
- webpack 代码压缩优化篇
- li序号 ul_ul ol li的序号编号样式
- ps怎样查看图片坐标
- 大众点评评论抓取-CSS加密破解
- Spring 4 - AOP
热门文章
- windows残留软件卸载
- kali2020提高权限到root
- iOS之深入解析如何检测“循环引用”
- 编写你的第一个 Django 应用,第 3 部分
- 4.Vue 模板语法
- Curses 中的 noecho() 函数
- Linux基础 —— Linux终端命令格式
- ubuntu下超级用户和普通用户
- LeetCode 287. Find the Duplicate Number (时间复杂度O(n)) + 链表判断环
- Codeforces 991E. Bus Number (DFS+排列组合)