博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
有关并查集的emmmm
阅读量:5045 次
发布时间:2019-06-12

本文共 2222 字,大约阅读时间需要 7 分钟。

并查集

顾名思义,并查集有三个用处

  • 并,即合并两个集合

  • 查,查询该元素所在的集合

  • 集,就指集合

现在来说一说并查集的基本操作:

- 初始化

首先,最开始的时候,我们假设所有的集合都只有一个元素,即只有自己(自己是自己的爸爸。。。)。所以简单初始化:

for(int i=1;i<=num;i++){        father[i]=i;        }

那么很好理解,如果你们的祖先一定是一个人,那你们是一家人对吧,所以 有公共祖先的两个元素在同一集合内

现在,我们可以对这num个集合操作了

- 认亲

我们把并查集的名字设为father,那么合并集合是不是就是认亲啊 = =;

好吧 再通俗点叫认祖宗


a:诶我们家没钱了QAQ

b:没事 我们家可以收养你

a:我还有一家人(数不清的爸爸们QAQ)挨饿啊

b:没事没事,我们家有的是钱,让你祖宗认我们家祖宗是爸爸,我们就是一家人了呗QVQ

a:是哦!!!!!


好吧,有点扯,不过就是这么回事(findfather函数参见下面的找爸爸)

void Union(int a,int b){        int faA=findfather(a);//找a祖宗        int faB=findfather(b);//找b祖宗        if(faA!=faB){            father[faA]=faB;//认爸爸            }        }

- 找爸爸

顾名思义,就是找你的爸爸的爸爸的爸爸(递归一波:) )

a:我看看。。。诶我祖宗是G诶

b:卧槽 我祖宗也是G

a+b:诶哟一家人

int father[maxn];    int findfather(int x){        while(x!=father[x]){//一直找到祖先为止            x=father[x];            }        return x;        }

实现的是并查集中 的作用,很好理解,就是像一条线一样,顺着线的源头一直找下去,直到找到一个自己的源头是自己元素,那么那个源头就是最大的爸爸了(就你那个老不死祖先QwQ)

但这种找发也有不足:如果G是a的 55555 代祖宗,那么a不是要找 55555 次才能找到?那不得累死QAQ

这样的一条链大大降低了找爸爸的效率

所以我们需要对其进行优化,不妨这样:

每次找到(最大)祖先,就替换自己的爸爸

理解如下,father[i]的值现在不代表i的爸爸了,而代表i的最大祖先


a:祖先?我看看

(打开族谱,发现只有一页:你的祖先是G

我的祖先是G

b:哦哦,我看看我的

(然后翻了55555页,每一页都是 { x的爸爸是Y } ,最后终于找到了father[G] = G)

f*ck,终于翻到了,我祖先是G


一对比,就发现路径压缩的好处了

具体代码实现:

int findfather(int v){        if(father[v]==v){            return v;//找到祖宗了= =            }        else{            int F=findfather(father[v]);//记住你祖宗            father[v]=F;//修改一下祖宗            return F;//一层一层回去            }        }

不过路径压缩的同时,也会出现一个问题

路人:诶,你们是你们家第几代啊?

a:(看着“你祖宗是G”)。。。

b:(翻那本族谱)我是55555代!!!


看到问题了吧

有关具体请参考

- 有关题目

刚接触并查集时,发现就几类题目:找亲戚,分组,通路...

诶哟,又不难啊哈哈哈

恩咳咳,后面发现不难个屁

那么好的,我们现在分析这类题目怎么写

首先,我们需要知道什么题面需要用到并查集

并查集一般涉及:

联通

想想,怎么把两块东西连在一起?

一个集合可以称作一个联通的块,连在一起就认祖宗呗

这就是最简单的并查集问题


P1551 亲戚

题目背景

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。

题目描述

规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。


P2839 畅通工程

题目描述

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

通常的,最简单并查集有一下几个考点

  1. 询问两点是否联通

(日常找爸爸【祖宗】)

  1. 询问有几个块

转换为找有几家人,再转换为找有几个老不死的祖宗:遍历所有点,若father[i] == i,就又找到一家)

  1. 还有的就自己动脑,哪那么多总结QVQ

这里归纳的是并查集的基础,掌握好基本操作,做几道板题,熟悉一下提醒,相信很快就能掌握


其实 后面 并查集 难到爆 一点都不难QAQ

转载于:https://www.cnblogs.com/Tony-Double-Sky/p/9283229.html

你可能感兴趣的文章
次序+“选择不重复的记录”(3)——最大记录
查看>>
Codeforces 450 C. Jzzhu and Chocolate
查看>>
[Unity3D]Unity3D游戏开发MatchTarget的作用攀登效果实现
查看>>
ACdream 1115 Salmon And Cat (找规律&amp;&amp;打表)
查看>>
JSON、JSONP、Ajax的区别
查看>>
AngularJS学习篇(一)
查看>>
【转载】 IP实时传输协议RTP/RTCP详解
查看>>
关于Xshell无法连接centos6.4的问题
查看>>
Linux系统的数据写入机制--延迟写入
查看>>
css3动画——基本准则
查看>>
javaweb常识
查看>>
Java注解
查看>>
时间>金钱
查看>>
元数据元素
查看>>
Visual Studio Code 构建C/C++开发环境
查看>>
web自己主动保存表单
查看>>
一个小的日常实践——高速Fibonacci数算法
查看>>
创建与删除索引
查看>>
java的基本数据类型
查看>>
机器学些技法(9)--Decision Tree
查看>>