- 1、本文档共32页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
(HDUACM201209版_07)并查集(最小生成树)
第七讲
并查集(Disjoint Set)
导引问题
在某个城市里住着n个人,现在给定关于 n个人的m条信息(即某2个人认识),
假设所有认识的人一定属于同一个单位,请计算该城市最多有多少单位?
如何实现?
什么是并查集?
英文:Disjoint Set,即“不相交集合”
将编号分别为1…N的N个对象划分为不相交集合,
在每个集合中,选择其中某个元素代表所在集合。
常见两种操作:
合并两个集合
查找某元素属于哪个集合
所以,也称为“并查集”
实现方法(1)
用编号最小的元素标记所在集合;
定义一个数组 set[1..n] ,其中set[i] 表示元素i 所在的集合;
1
2
3
4
5
6
7
8
9
10
1
2
1
4
2
6
1
6
2
2
i
Set(i)
不相交集合: {1,3,7}, {4}, {2,5,9,10}, {6,8}
方法(1)——效率分析
find1(x)
{
return set[x];
}
Merge1(a,b)
{ i = min(a,b);
j = max(a,b);
for (k=1; k=N; k++) {
if (set[k] == j)
set[k] = i;
}
}
Θ(1)
Θ(N)
有待改进?
对于“合并操作”,必须搜索全部元素!
树结构如何?
实现方法(2)
每个集合用一棵“有根树”表示
定义数组 set[1..n]
set[i] = i , 则i表示本集合,并是集合对应树的根
set[i] = j, ji, 则 j 是 i 的父节点.
1
2
3
4
5
6
7
8
9
10
1
2
3
2
1
3
4
3
3
4
方法(2)——效率分析
find2(x)
{
r = x;
while (set[r] != r)
r = set[r];
return r;
}
merge2(a, b)
{
if (ab)
set[b] = a;
else
set[a] = b;
}
Θ(1)
最坏情况Θ(N)
一般情况是…?
困惑~~~
性能有本质改进?
如何避免最坏情况?
避免最坏情况
方法:将深度小的树合并到深度大的树
实现:假设两棵树的深度分别为h1和h2, 则合并后的树的高度h是:
max(h1,h2), if h1h2.
h1+1, if h1=h2.
效果:任意顺序的合并操作以后,包含k个节点的树的最大高度不超过
优化后算法及效率
merge3(a,b)
{ if (height(a) == height(b)) {
height(a) = height(a) + 1;
set[b] = a;
} else if (height(a) height(b))
set[a] = b;
else
set[b] = a; }
find2(x)
{
r = x;
while (set[r] != r)
r = set[r];
return r;
}
最坏情况Θ(log N)
Θ(1)
进一步优化——路径压缩
思想:每次查找的时候,如果路径较长,则修改信息,以便下次查找的时候速度更快
步骤:
第一步,找到根结点
第二步,修改查找路径上的所有节点,将它们都指向根结点
带路径压缩的查找算法
find3(x)
{
r = x;
while (set[r] r) //循环结束,则找到根节点
r = set[r];
i = x;
while (i r) //本循环修改查找路径中所有节点
{
j = set[i];
set[i] = r;
i = j;
}}
路径压缩示意图
示例—畅通工程(HDOJ-1232)
题目描述:
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
题目分析
最赤裸裸的并查集,无话可说~
附:参考源码(HDOJ-1232)
#include stdio.h
int bin[1002];
int findx(int x)
{
int r=x;
while(bin[r] !=r)
r=bin[r];
return
您可能关注的文档
- (2015中考精英)2015中考英语人教版复习课件:中考题型7 句子运用.ppt
- (2015中考精英)2015中考英语人教版复习课件:第9讲 八年级(下)Units 1~2.ppt
- (2013秋)第三章生产运作流程分析.ppt
- (2015聚焦中考+安徽专用)2015中考英语九年级复习精品课件:第7讲+八上Units+5-6.ppt
- (2016人教版)六年级数学下册课件_比例的整理和复习.ppt
- (2016最新版)在职攻读硕士学位全国联考英语考试大纲词汇.doc
- (2014新人教版)第六章北方地区第四节 祖国的首都──北京.ppt
- (2016年最新版本)9.2世界多极化:不可逆转.ppt
- (3-5) 相对渗透率.ppt
- (3.1)情绪管理.ppt
文档评论(0)