`
shuofenglxy
  • 浏览: 195285 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ZZ并查集

阅读更多

原文出处:http://blog.sina.com.cn/s/blog_5ec05ef30100cp7f.html

作者:angela

 

所谓并查集,它是一个集合,这个集合的元素也是集合,他支持三种操作
MakeSet(x),建立一个只有一个元素x的集合X0,将这个集合放入并查集中;
FindSet(x),在并查集中寻找一个元素S(注意并查集的元素S也是集合) ,满足
x属于S; Union(x,y), 将并查集中的元素S1,S2合并,其中x属于S1,y属于S2。

下面说说并查集的实现,其实很简单,用树来实现。所有属于同一集合的元素属于
同一棵树,这样我们就可以用数根来表示一个集合,要找到某个元素属于哪个集合
,只要找到这个元素所在的树的树根;要合并两个集合,只要合并两棵树。一般比
较方便的方法是用父亲数组Parent[]来表示树,Parent[i]就是节点i的父结点,树
根的父结点就是它本身。这样很容易根据某个节点找到他的根,也很容易合并两棵
树。但是我们要考虑效率问题。在最坏的情况下,一棵树退化成一个单链表(想象
一下所有的结点只有唯一的儿子节点),这样如果链表长度为L,从一个节点找到
他的根也需要L次运算,对于一共有n个节点元素的并查集,FindSet平均情况和最
坏情况下的复杂度都是O(n),效率并不高。对于一棵树而言,如果树的高度为H,
那麽从叶节点只要经过H次运算就可以找到树根,所以我们应该尽量减少树的高度
,最好的情况是树的高度只有1层,这样就是一个树根下面有很多儿子,这些儿子
都是树叶。但是如果两棵这样的树合并,数的高度就会增加,比如高度为H1的树
T1和高度为H2的树T2合并,得到的树的高度有两种情况: max { H1, H2+1}或者
max{H1+1, H2},前一种情况是T2的根作为T1的根的儿子,后一种情况则是T1的根
作为T2的根的儿子。这就说明经过多次Union操作以后,树的高度会增加。为了使
得树的高度尽量地小,我们应该将较矮的树合并到较高的树上,因此我们用一个数
rank记录每棵树的高度,rank[i]就是以i为根的子树的高度,在合并的时候就可以
根据rank的值进行合并,Union的代码如下:

// 合并x,y所在的集合,并返回交集
int Union(int x, int y)
{
x = FindSet( x ); // 找到x所在的树的根
y = FindSet( y ); // 找到y所在的树的根
if( x == y ) return x; // -1表示空集
if( x == -1 ) return y;
if( y == -1 ) return x;
if( Rank[x] > Rank[y] ) { // 将较低的树合并到较高的树上
Parent[y] = x;
return x;
}

else {
Parent[x] = y;
if( Rank[x] == Rank[y] ) Rank[y]++; // 改变树的高度
return y;
}
}

Union其实是一种启发式算法,rank[i]就是启发函数值。

另外,为了降低树的高度,我们在FindSet的时候也会压缩路径,比如原来a是树根
,b是a的儿子,c是b的儿子,d是c的儿子,我们调用FindSet(d)找d所在的树的树
根,在找的同时,我们改变该树的结构,使得调用FindSet(d)结束以后树的结构变
为a是树根,b是a的儿子,c也是a的儿子,d也是a的儿子。这就叫做路经压缩。因
此FindSet代码如下:

// 返回到元素i所属的集合的代表元素, 同时进行路径压缩
int FindSet(int i)
{
if( ( i == -1 ) || ( i >= CAPACITY ) ) { // -1表示空集
return -1;
}

else {
if( ( Parent[i] != -1 ) && ( Parent[i] != i ) )
Parent[i] = FindSet( Parent[i] ); // 这句话进行路径压缩
return Parent[i];
}
}

并查集的效率很高,可以证明,通过这种树形结构实现的带启发式路径压缩的并查
集,FindSet和Union操作的平均代价是O(lgn),这和二分查找的复杂度一致,可以
证明这已经是理论上最好的算法了,不可能有更好的算法了。如果不进行这种路经
压缩的话,并查集就退化成了链表,在同一链表中的元素属于同一集合,这样的话
FindSet的复杂度是O(n)。

并查集也是很常用的数据结构,有一道题目“亲戚”,也要用并查集:

题目: 亲戚(Relations)

  或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女
婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否亲戚应该是可
行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么
检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。

  为了将问题简化,你将得到一些亲戚关系的信息,如同Marry和Tom是亲戚,
Tom和Ben是亲戚,等等。从这些信息中,你可以推出Marry和Ben是亲戚。请写一个
程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

  参考输入输出格式 输入由两部分组成。

  第一部分以N,M开始。N为问题涉及的人的个数(1 ≤ N ≤ 20000)。这些人的
编号为1,2,3,…,N。下面有M行(1 ≤ M ≤ 1000000),每行有两个数ai, bi,表示
已知ai和bi是亲戚。

  第二部分以Q开始。以下Q行有Q个询问(1 ≤ Q ≤ 1 000 000),每行为ci,
di,表示询问ci和di是否为亲戚。

  对于每个询问ci, di,若ci和di为亲戚,则输出Yes,否则输出No。

  样例输入与输出

输入relation.in
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9

输出relation.out
Yes
No
Yes
如果这道题目不用并查集,而只用链表或数组来存储集合,那么效率很低,肯定超
时。

分享到:
评论

相关推荐

    JSF架构图zz

    JSF框架提供了一种易于使用的API来构建动态Web应用程序,并且通过其丰富的特性集,如表单处理、验证、国际化支持等,使得开发者能够快速地创建出功能完备的Web应用。 #### 二、JSF架构组成 根据给定的内容,“JSF...

    VBA数据库查询及数据自动导出多Excel报表

    ' 处理记录集 End With ``` - **Open 方法**: 用于打开 Recordset 对象,参数包括 SQL 查询语句、Connection 对象等。 - **CommandTimeout**: 设置命令执行的超时时间,单位为秒。 ### 将查询结果自动导出到多个 ...

    BDD-ZZ1:ZZ1上的TD等基础知识-SQL

    2. **并行处理**:Teradata的设计充分利用了并行计算,允许同时处理多个查询,使得处理大数据集时的性能显著优于传统的单线程数据库。 3. **DML操作**:在Teradata中,对数据的插入、更新和删除操作需要考虑到其...

    指标平台加速零售数字化转型zz.pptx

    为了解决上述挑战,Kyligence Zen 应运而生,它是一款集业务模型、指标管理、指标加工、数据服务于一体的一站式指标平台。该平台旨在通过提供高效的数据处理和分析能力,帮助零售企业实现从数据驱动到指标驱动的转变...

    VivaNavy.9fbfsplbf6.cf4n4ZZ

    标题“VivaNavy.9fbfsplbf6.cf4n4ZZ”和描述中并未直接提供具体的IT知识点,但考虑到标签是“HTML”,我们可以推测这个压缩包可能包含与HTML(超文本标记语言)相关的学习资源或项目。HTML是网页开发的基础,用于...

    算法数据结构学习视频教程,算法和数据结构的基础概念、进阶技巧以及特定算法的应用和实现

    第16节 并查集及其相关题目.mp4 第17节 图.mp4 第18节 认识一些经典递归过程.mp4 第19节 暴力递归到动态规划(一).mp4 第20节 暴力递归到动态规划(二).mp4 第21节 暴力递归到动态规划(三).mp4 第22节 暴力递归...

    py源码实例实例名言查询

    这可能包括连接数据库、执行SQL查询语句、处理结果集等操作。 4. 网络编程:如果名言数据是在线可访问的,可能会使用Python的网络库(如requests或urllib)来发送网络请求并获取数据。 5. 数据处理:获取到名言...

    AT指令,短信猫串口调试

    AT指令是串行通信中的一种标准命令集,主要用于配置和控制GSM/GPRS模块或“短信猫”,这些设备常用于实现远程通信中的短信收发功能。在VB(Visual Basic)编程环境中,我们可以创建应用程序来与短信猫进行交互,实现...

    bom.rar_BOM_storedprocedure_物料

    "zz_sp_BomSumExport"可能是一个用于汇总物料BOM数据并导出的特定功能,例如,它可能用于生成物料清单报告,展示产品及其所有组成部分,包括数量、层次结构和成本信息。 标签“bom”、“storedprocedure”和“物料...

    数学建模数据集全国银行名称及所在地数据mysql/sql

    1. 数学建模与数据集:数学建模是利用数学的方法和工具来解决实际问题的一种方法论,它是将现实世界中的问题抽象、简化并构建数学模型,然后通过数学推导、计算机模拟等方式求解模型,最终对现实问题给出定量的解答...

    实例MATLAB实现学生成绩查询系统源代码程序

    它集数值分析、矩阵运算、信号处理和图形显示于一体,被广泛应用于工程计算、控制设计、信号处理和通信等领域。MATLAB提供了一个交互式的环境,允许用户通过编写脚本或函数来快速实现复杂算法。它的另一个特点是拥有...

    中航信Eterm协议解析

    例如,Eterm协议可能定义了一套特定的命令格式,如"XX YY ZZ",其中"XX"代表命令类型,"YY"表示操作码,"ZZ"可能包含附加参数。在实际应用中,代理人可能输入如“CA QS 20220701”这样的指令来查询某一天CA航空公司...

    数学建模数据集外商直接投资数据大总结30年世界数据

    为了使用这些数据,用户需要有百度网盘账号并登录后,通过提供的链接下载数据集文件。 这份数据集的标签显示其可以用于数据科学、统计分析、商业分析、金融分析等领域的教学和研究。同时,数据集的特性表明它适用于...

    5152单片机proteus仿真和源码用定时器T0查询方式P2口8位控制LED闪烁

    5152单片机属于8051系列的一种扩展型号,其内部结构和指令集与传统的8051兼容。它具有更多的RAM空间以及更多的I/O口线,适用于需要较大存储空间和更多外部接口的应用场合。5152单片机的主要特点包括: 1. **内部...

    广工 数据库 考题(2)

    - 可以通过连接`SB`和`ZZ`表,并使用`INNER JOIN`或子查询的方式找到匹配的记录。 4. **查询出大修过的设备中每种设备大修费用的平均值**: - 通过聚合函数`AVG()`计算费用的平均值,并使用`GROUP BY`子句对不同...

    vim常用命令vim常用命令vim常用命令

    - `ZZ`: 保存当前文档并退出VIM。 5. **编辑操作**: - `dw`: 删除一个单词,需要先将光标移动到单词开头。 - `daw`: 删除光标所在单词。 - `dnw`: 删除n个单词。 - `dne`: 删除到下一个单词末尾。 - `dnl`: ...

    算法文档无代码一些与树有关的题目

    - 并查集(Disjoint Set Union, DSU)的实现和应用 这些知识点都是算法设计和数据结构领域中处理树型结构时可能需要掌握的关键点。不同类型的树结构适用于解决不同类型的算法问题,例如二叉搜索树适用于快速查找和...

    java调用Oracle存储过程

    另外,如果存储过程返回游标(结果集),可以通过`ResultSet`接口进行处理。记得检查存储过程的返回值,它通常是一个表示成功与否的状态。 在开发过程中,可以使用诸如IntelliJ IDEA或Eclipse这样的IDE进行调试,...

    文档数据结构之最小生成树Prim算法

    - **数据结构需求不同**:Prim算法通常需要维护一个优先队列来更新顶点的最小距离,而Kruskal算法需要使用并查集来避免形成环路。 - **应用场景差异**:两者都可以应用于求解最小生成树问题,但在某些特定情况下,一...

Global site tag (gtag.js) - Google Analytics