- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
并查集在信息学竞赛中的应用
并查集在信息学竞赛中的应用
广东省中山纪念中学 宋新波
【摘要】:
并查集主要应用于涉及到几个不相交子集的查找和合并运算。本文着重讲解了这两个运算,查找运算时通过路径压缩可以大大提高效率。然后通过两个例子讲述了并查集的应用。
【关键词】:并查集
n个不同元素的集合,可能被分成若干个不相交子集,有时候一些问题需要涉及到查找某个元素所在集合以及合并两个集合的运算,这时候可以使用并查集。
在每个子集中,用其中一个元素x作为集合的名字,集合中的其他元素都和x连通。如s={1,2,3,4,5,6,7,8}有3个子集:s1={1,3,4},s2={2,5,7},s3={6,8},可以用1,2,6分别表示这3个集合。
我们把查找运算定义为find(x),表示找出x所在集合。如find(5)的结果为2,即包含5的那个集合的名字为2;把合并运算定义为union(x,y), 表示把包含元素x和y的两个集合合并成一个大的集合,并集的名字或者是原来x的那个集合的名字,或者是原来y的那个集合的名字。如执行完union(3,5)后原来两个集合{1,3,4}和{2,5,7}被合并成一个集合{1,2,3,4,5,7},该集合的名字可以取1,也可以取2。
我们我设计这两种运算的有效算法。为此需要一种数据结构,它既要简单,同时又要考虑到能有效地实现查找和合并这两种运算。满足条件的数据结构是用根树来表示每个集合,集合中的元素存储在节点中,树中除根节点外的每个元素x都有一个指向父节点p(x)的指针。根有一个空指针,用作集合的名字或集合的代表。这样产生了一个森林,其中每一棵树对应于一个集合。
对于任意元素x,用root(x)表示包含x的树的根。那么find(x)返回就是root(x)。由于合并运算必须有两棵树的根作为参数,所以union(x,y)实际上就是union(root(x),root(y))。
具体实现时,可以方便地用数组A[1..N]来表示,A[i]表示元素i的父节点(1=i=n),如果某个元素j的A[j]为0,说明j没有父节点,是树根,j就可以用来表示这个集合的名字。如下图(a)是对应3个集合的4棵树,称为树表示法,(b)是数组表示法。
(a)
(b)
1 2 3 4 5 6 7 8 9
0 1 1 0 1 9 9 0 4
上面定义了数据结构,接下来?谈谈find(x)和union(x,y)运算。
Find(x)实现很简单,只是沿着从x开始直到根节点的路径,最后返回root(x)
Union(x,y)运算要求先算出root(x),root(y),然后令root(x)指向root(y),即p(root(x))=root(y)
为了改善时间,这里我们介绍一种措施:路径压缩。
路径压缩主要是提高查找find(x)的效率。在find(x)的运算中,找到根节点y之后,我们再一次编历从x到y的路径,并沿着路径改变所有节点的父节点的指针,使它们直接指向y,为以后的查找节省时间。路径压缩的执行过程如下图所示:
(a) (b)
在执行find(4)的运算中,找到集合名称为1。因此,从4道1的路径上每个节点的父节点的指针都指向1。路径压缩增加了执行查找运算的工作量,但这种耗费在穗沪的子序列的查找运算中得以偿还。
并查集主要用于涉及几个不相交子集中的查找和合并操作。上面的例子中,我们只关心每个元素所在集合,所以我们只记录p(x)表示元素x的父节点就足够了,但有时不仅要知道x的父节点,还要知道它和父节点之间的某种关系。
接下来,我们通过两个例子来讲述这种并查集。
例一:食物链
eat.pas/c/cpp
动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B, B吃C,C吃A。
现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。
有人用两种说法对这N个动物所构成的食物链关系进行描述:
第一种说法是“1 X Y”,表示X和Y是同类。
第二种说法是“2 X Y”,表示X吃Y。
此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的。当一句话满足下列三条之一时,这句话就是假话,否则就是真话。
当前的话与前面的某些真的话冲突,就是假话;
当前的话中X或Y比N大,就是假话;
当前的话表示X吃X,就是假话。
你的任务是根据给定的N(1=N=50,000)和K句话(0=K=100,000),输出假话的总数。
输入文件(eat.in)
第一行是两个整数N和K,以一个空格分隔。
以下K行每行是三个正整数?D,X,Y,两数之间用
文档评论(0)