并查集简单模板及其解释
发布日期:2021-06-29 11:10:11
浏览次数:2
分类:技术文章
本文共 2491 字,大约阅读时间需要 8 分钟。
1;初始化;据具体情况保存和初始化需要的内容 ;
初始化必须要进行的。把每个节点所在集合初始化为其自身。O(n)//初始化;划分类,就是有多少个元素就有多少个等价类 for(i = 1; i <= n; i++){ //要从1开始; ba[i] = i;//初始化; }
2;查找;查找该元素所在集合;
没压缩版;int find(int a)//无压缩的查找 ,找根节点,用函数find(a)找到a的最近的祖先。 { while(ba[a] != a){//当祖先不等于编号时; a = ba[a];//将祖先的编号赋值给a; } return a;//返回a的最近祖先;(这里的祖先就是前面一个) }
3;合并
void marget(int a, int b)//先找到a,b各自的祖先然后再把祖先链接起来; { int fa = find(a);//将各自的祖先赋值下来 int fb = find(b); if(fa != fb){ //如果两个的祖先不是同一个祖先 ba[fa] = fb;//则将编号fa的祖先赋值为 fb(也就是b的祖先)下面会有模拟的。 }}
4;最先祖先的个数;要输出有好多个最先祖先;只需要判断pa[i]==i;
count = 0;//这里视情况而定 for(i = 1; i <= n; i++){ if(ba[i] == i){ //等下又模拟的; count++;//count就是表示最先祖先的个数 } }
4压缩版的查找
//找到该元素所在集合的最初元素;
找元素所在集合的代表元(因为用了路径压缩,路径压缩的主要目的是为了尽快的确定元素所在的集合)
int findset(int v) //循环{ int t1,t2=v; while(v!=pa[v]) //与前面一样的,找到v**最近**的祖先 v=pa[v]; while(t2!=pa[t2]){ //找到v**最先**的祖先; t1=pa[t2]; pa[t2]=v; t2=t1; } return v; }
int findset(int x)//递归{ if (x != pa[x]) { pa[x] = findset(pa[x]); } return pa[x];}
来模拟一下是怎么实现并查集的吧?
我以下的祖先,也表示了父亲,就是把凡是可以生成它的都是他的祖先;方便描述点; 定义一个数组pa[100000]; pa的下标表示该元素的编号; pa的内容表示该元素的祖先;1;最前面的初始化应该知道吧;就是把每个元素的祖先都定义为自己;
2;查找那里;就是当ba[a] != a时就是a的祖先不是a,表示a有祖先了。就将它最近的祖先返回;而那个压缩的就是返回它的最前面的祖先。
3;合并;就是判断ab的祖先是不是出自同一祖先,如果不是就将pa[a1]=b1;意思就是说把编号为a1(就是a的祖先)的祖先赋值为b1;
下面来模拟一遍吧;
定义数组s; s==下标==1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;===内容= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;最前面初始化;
1 2连接== 2 | 2 | 3 | 4 | 5 | 6 | 7 | 8;将pa[1]=2;就是这个代码; 3 4连接== 2 | 2 | 4 | 4 | 5 | 6 | 7 | 8 ;将pa[3]=4;就是这个代码; 1 4连接== 2 | 4 | 4 | 4 | 5 | 6 | 7 | 8;将pa[2]=4;就是这个代码; 突然间是不是更晕了,然而答案已近出来了。 用判断pa[i]==i;来判断count求出最先祖先的个数; 就是5;是不是;答案就是5啊、意思就是我们的代码作用就是留下pa[i]=i;看一个套用模板的题目;
hdu1232畅通工程; 套用模板得出;#includeint ba[1004]={ 0};int find(int a){ while(ba[a] != a){ a = ba[a]; } return a;}void marget(int a, int b){ int fa = find(a); int fb = find(b); if(fa != fb){ ba[fa] = fb; }}int main(){ int n, m, i,a,b,count; while(scanf("%d %d",&n, &m)!=EOF&&n!=0){ for(i = 1; i <= n; i++){ ba[i] = i;//初始化; } for(i = 1; i <= m; i++){ scanf("%d %d",&a, &b); marget(a, b); } count = -1;//这里是求要多少个路,则是从-1开始 for(i = 1; i <= n; i++){ if(ba[i] == i){ count++; } } printf("%d\n",count); } return 0 ;}
转载地址:https://blog.csdn.net/zw1996/article/details/51317364 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
做的很好,不错不错
[***.243.131.199]2024年04月29日 14时40分48秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
值得收藏!268条PCB layout设计规范
2021-07-02
Keil升级了,Keil Studio 来了!
2021-07-02
关于RS-485总线,这篇很详细
2019-04-29
关于2021年电赛的一些想法,看到就是赚到!
2019-04-29
教你一秒分辨真假芯片!
2019-04-29
抽奖 | 送STM32开发板
2019-04-29
光立方,永远的神!
2019-04-29
学习STM32很简单?
2019-04-29
电赛 | 电源题软件如何准备?
2019-04-29
手把手教你DIY一款属于自己的万能红外遥控器!
2019-04-29
速看 | 电子元器件如何确定好坏?
2019-04-29
485通信自动收发电路,历史上最详细的解释
2019-04-29
【视觉盛宴三】不好意思,这些线材接口的横截面真的没见过
2019-04-29
一位头发发白的神人教你怎么写程序,运维,买电脑,写文章,平面设计!
2019-04-29
【第二期】那些设计漂亮、有创意的电路板!
2019-04-29
【第三期】那些设计漂亮、有创意的电路板!
2019-04-29
继续推荐公众号~
2019-04-29
「第二篇」全国一等奖,经验帖。
2019-04-29
「第三篇」全国电子设计竞赛,这些你必须知道的比赛细节,文末附上近十年电赛题目下载...
2019-04-29
5G小科普(漫画版,So easy!)
2019-04-29