网站大量收购独家精品文档,联系QQ:2885784924

并查集(最终版).ppt

  1. 1、本文档共56页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
例6:食物链(NOI2001 ) 动物王国中有三类动物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句话有的是真的,有的是假的。 你从头开始一句一句的读入这K句话。当你读到的话满足下列三条之一时,这句话就是假的,否则就是真的。 1)? 当前的话与前面的某些真的话冲突; 2)? 当前的话中X或Y比N大; 3)? 当前的话表示X吃X。 你的任务是根据给定的N(1=N=50,000)和K个条件(0=K=100,000),输出假话的总数。 输入: 第一行是两个整数N和K,以一个空格分隔。 以下K行每行是三个正整数?D,X,Y,两数之间用一个空格隔开,其中D表示说法的种类。 若D=1,则表示X和Y是同类。 若D=2,则表示X吃Y。 输出: 只有一个整数,表示假话的数目。 输入/输出及样例 输入样例: 100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5 输出样例: 3 //假 //真 //真 //假 //假 //真 //真 小结: “并”、“查”、“集”;操作对象是抽象的集合;最常用操作:查找、合并 动态、实时查询 并查集的路径压缩只有在元素之间的特性存在递推关系时才可以使用。 Thank you 如果是个欧拉回路一笔就可以完成,如果是个其它连通集,要根据这个集合的奇度数而定,笔划数=奇度个数/2,用并查集来判断有多少个连通集,然后用vector来存这些连通集,通过判断度数是奇偶性来确定是否为欧拉回路;总之笔划数 = 奇度数/2 + 欧拉回路数; 在图论中,连通图基于连通的概念。在一个无向图 G 中,若从顶点vi到顶点vj有路径相连(当然从vj到vi也一定有路径),则称vi和vj是连通的。 每个集合对应一个链表,它有一个表头,每一个元素有一个指针指向表头,表明了它所属的类,另有一个指针指向它的下一个元素,同时为了方便实现,再设一个指针last表示链表中的最后一个元素(表尾)。 当然,由于处理的对象一般都是连续整数,所以,可以选择静态数组(通过下标)来模拟实现,如: type node = record head,next,last:integer; end; var S : array[1..maxn] of node; 并查集的链表实现 MAKE-SET(x):S[x].head = x;S[x].next = 0; FIND-SET(x):return S[x].head; 两个过程的时间复杂度都为O(1)。 采用链表时,当有两个元素(x,y),若FIND-SET(x)≠ FIND-SET(y),则两者对应不同的集合,需要将两个链表合并,做法是将一个表的表头直接接到另一个表的表尾,这一步操作看似很简单,但势必造成修改后需要把接上去的那个表的所有head值修改,这需要线性的赋值操作,其复杂度与选择接在尾部的链表长度成正比。 UNION(x,y): 假设UNION(x,y)的参数是有序的,即把y属于的集合合并到x的集合有两种实现方法: (1)简单实现 不考虑任何因素,出现FIND-SET(x)≠ FIND-SET(y)时,直接将y的表头接到x的表尾,同时将y中所在集合元素的head值设为FIND-SET(x)。同时x的表尾也应该设为原y表的表尾。 注意:last指针其实只要在表头结点中记录即可,因为每一次查到FIND-SET(x)都可以得到表头元素。而链表中其他元素重新记录last是无意义的。 我们总是把y接到x里去,那么如果y所在的集合非常大,每次赋值的代价就会非常高,考虑输入数据的特殊性,比如出现输入为: (2,1),(3,1),(4,1),(5,1),(6,1) , … ,(n,1) 最坏情况下时间复杂度为O(n^2)。 (2)快速实现 上述简单实现非常不理想,针对y可能比较大的这个问题,可以很快产生一个聪明的想法:不妨比较x和y所在集合的大小,从而作出选择,把较短的链表接在较长的尾部,这样效果是一样的,但耗费肯定不比原来差。这就是快速实现的思路。可以在node里多设一个域number,用来记录此条链表中成员的个数。显然number记录在表头元素中即可,将两表合并的时候,

文档评论(0)

asd522513656 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档