算法高级部分--并查集

本文深入介绍了并查集这一数据结构,通过江湖人物关系的例子阐述了其初始化、查找祖宗及合并操作的原理。并查集用于解决联通性问题,例如在畅通工程中确定最小道路建设数量,以及在方块栈游戏中跟踪方块的移动。文中提供了相关算法代码,并强调了路径压缩的关键作用。
摘要由CSDN通过智能技术生成

1.并查集是什么?

用一个例子来说明。。。
江湖不是打打杀杀,是人情世故。在一个江湖中,有许许多多的人物张三,李四,王二,麻子。为了方便起见用编号 1 2 3 4 5 6 7 8 9…
初始时,他们互不相识
在这里插入图片描述
某一天,2号和7号一见如故,又某一天 4和5号一见钟情,7号和8号义结金兰等等等…
随着时间发展,因为某种原因江湖乱了起来,腥风血雨。这天4号和7号相遇了,4号和7号也不知道对方是不是自己朋友的朋友,万一是自己人动手可就不太好了
于是武林关系谱诞生了,当2和7为朋友时,在谱上划一条由2到7的箭头(7到2也可以,没有影响),这样将关系表示出来,我们就可以知道是不是有关系了。
在这里插入图片描述
可江湖人太多了,如果按这样的方式表示的话,查一个人的关系可能要一直查到其路径尽头,显然太复杂了,如果能优化就好了。
于是,我们可以在一群人中选出带头大哥来代表,若有x和y是朋友,只要让x的带头大哥和y的带头大哥有建立关系就可以了。
具体步骤如下:
初始时,互不相识,每个人都是自己的带头大哥(初始化操作)
在这里插入图片描述
2和7是朋友 4和5是朋友
在这里插入图片描述
现在有这种关系并入 (加入):7和8是朋友,先找7的带头大哥2,8的带头大哥8,2和8建立联系。(合并操作)
在这里插入图片描述
合并4 8,同样的操作
![在这里插入图片描述](https://img-blog.csdnimg.cn/fddf15839a504921b64539518e1900fe.png
合并5 3,这一步最为不同,也最为关键。找5的带头大哥4,4找到2。返回时,可以利用递归将得到的带头大哥号返回给所有路径上的结点,这一步叫做路径压缩。结合代码来理解:

int find(int x){	
	if(x!=fa[x])
		fa[x]=find(fa[x]);
	return fa[x];
}
//上述操作如下
find(5)-->5不是带头大哥,find(4)-->4不是带头大哥,find(2)-->2是带头大哥,2返回上一层
-->设fa[4]=2,2返回上一层-->设fa[5]=2--返回2结束

2和3建立联系
在这里插入图片描述
补充一点:是先路径压缩了再合并,而不是合并了再路径压缩。所以合并4和8后没有立刻路径压缩,而是合并5 3 时再压缩

2.算法步骤代码

2.1 初始化

void init(){
	for(int i=1;i<=n;i++)
		fa[i]=i;
}

2.2 查找祖宗并统一祖宗

//找祖宗并同统一祖宗 
int find(int x){
	if(x!=fa[x])
		fa[x]=find(fa[x]);
	return fa[x];
}

2.3合并操作

void Union(int x,int y){
	int a=find(x);
	int b=find(y);
	if(a!=b){
		b=fa[a];
	}	
} 

3.经典例题

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

  2. 方块栈
    贝西正在玩游戏,方块编号为1~N(1<= N <= 1000), 开始时每个方块都相当于一个栈。贝西执行一系列操作, 操作类型有两种: MXY,将包含X的栈整体移动到包含Y的栈顶部; C X,查询X方块下的方块数量。 请统计贝西每个查询操作的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值