- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
并查集 Yali 朱全民 分离集合 在有的问题中,需要对不相交的集合(disjoint set)进行这样两种操作: 检索某元素属于哪个集合 合并两个集合 能够维护这两个操作的数据结构,我们称之为并查集。 并查集的森林实现 一般来说我们用森林的结构实现并查集 在森林中,每棵树代表一个集合。用树根来表示这个集合。 合并操作:两个集合S1、S2合并,将其中的一个树根作为另一个树根的子树即可。 查找操作:对于一个元素u的查找,顺着u往上找,直到线索到根节点,也就确定了u所在的集合。 两个优化 启发式合并: 在合并集合S1、S2的时候,我们让较小的树成为较大的树的子树。这里可以是深度、节点个数等启发函数来比较树的大小。 路径压缩: 我们在查找完u至根节点的路径之后,一般将这条路径上的所有节点的父节点都设为根节点,这样可以大大减少之后的查找次数。 并查集的时间复杂度 可以证明,经过启发式合并和路径压缩之后的并查集,执行m次查找的复杂度为O(mα(m)) 其中α(m)是Ackermann函数的某个反函数,你可以近似的认为它是小于5的。所以并查集的单次查找操作的时间复杂度也几乎是常数级的。 例一 银河英雄传说(NOI2002) 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争。泰山压顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨威利组织麾下三万艘战舰迎敌。 杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气。在这次决战中,他将巴米利恩星域战场划分成30000列,每列依次编号为1, 2, …, 30000。之后,他把自己的战舰也依次编号为1, 2, …, 30000,让第i号战舰处于第i列(i = 1, 2, …, 30000),形成“一字长蛇阵”,诱敌深入。这是初始阵形。当进犯之敌到达时,杨威利会多次发布合并指令,将大部分战舰集中在某几列上,实施密集攻击。合并指令为M i j,含义为让第i号战舰所在的整个战舰队列,作为一个整体(头在前尾在后)接至第j号战舰所在的战舰队列的尾部。显然战舰队列是由处于同一列的一个或多个战舰组成的。合并指令的执行结果会使队列增大。 例一 银河英雄传说(NOI2002) 然而,老谋深算的莱因哈特早已在战略上取得了主动。在交战中,他可以通过庞大的情报网络随时监听杨威利的舰队调动指令。 在杨威利发布指令调动舰队的同时,莱因哈特为了及时了解当前杨威利的战舰分布情况,也会发出一些询问指令:C i j。该指令意思是,询问电脑,杨威利的第i号战舰与第j号战舰当前是否在同一列中,如果在同一列中,那么它们之间布置有多少战舰。 作为一个资深的高级程序设计员,你被要求编写程序分析杨威利的指令,以及回答莱因哈特的询问。 例一 银河英雄传说(NOI2002) 观察这个题目,开始时每条战舰作为独立的队列。随着M命令的发布,分离的队列不断合并。 而且途中我们需要知道一些元素(战舰)的信息 这些性质启发我们应用并查集的数据结构解决 例一 银河英雄传说(NOI2002) 由于我们要得到的信息除了某条战舰在哪个队列,还要知道它在该队列中的位置。因此需要对并查集进行扩充。 定义: a[i]:战舰i暂时标记为属于以战舰a[i]为首的队列,称战舰a[i]为战舰i的父节点 b[i]:战舰i到战舰a[i](包括战舰a[i])之间的战舰数量,称b[i]为战舰i到战舰a[i]的深度。 c[i]:战舰i所属队列后方(包括战舰i本身)的战舰数量(注意:此变量只有当a[i]=i时才有意义),称c[i]为队列长度。 例一 银河英雄传说(NOI2002) 初始时:a[i]=i,b[i]=0,c[i]=1 对于每个M i j命令,需要进行如下操作: 对战舰i,j进行查找和路径压缩 设a[i]=r1,a[j]=r2且r1r2,则:a[r1]=r2,b[r1]=c[r2],c[r2]=c[r1]+c[r2] 对于每个C i j命令,需要进行如下操作: 对战舰i,j进行查找和路径压缩 判断是否有a[i]=a[j],如是则表示他们是同一队列,输出|b[i]-b[j]|-1;如果不是则输出-1 例一 银河英雄传说(NOI2002) 关于战舰i的路径压缩的步骤: 从i出发寻找根root,并累计从i到根root的深度,得到b[i] 再次遍历从i出发到root的路径。对于途中的每一个节点k(假设在修改k之前a[k]=a1,b[k]=b1),则我们根据已经修改过的战舰k的a、b值对战舰a1的a、b值进行修改,即: a[a1]=root,b[a1]=b[k]-b1
文档评论(0)