并查集(一)
今天做了几道最基础的并查集题目,复习了一下并查集结构
并查集,就是一种支持合并与查询的数据结构,有些老的翻译会翻译成不相交集合的数据结构.
并查集可以用树或链表实现,不过一般都是用树实现的.
思路很简单,用Father[i]表示i的祖宗,一开始是他自己,合并时把一个的祖宗标记为另外一个的祖宗就行了.查询的时候看看他祖宗是不是他自己,不是的话就去找他老爸的祖宗.
并查集的分析很难,算法导论与数据结构与算法分析都花了不少篇幅来描述.
并查集的常用优化方法有路径压缩(即找祖宗的时候把自己的老爸标记为老祖宗),按轶(高度)合并/按大小合并等,两种人都能显著改善运行时间.
并查集的代码很巧妙,简洁易懂.不过我打的时候经常在套不套find(即很多人用的Getfather)或f(即很多人用的Father)上出现问题.
并查集在涉及集合的问题,图论问题中都有有广泛应用,学起来也很容易.下面是今天我做的水题,属于最基础的并查集题目,基本上只要会写并查集都能过的.
tyvj p1017
rqnoj 331 343 577
577有必要提一下,判断我敌人的敌人是我的朋友,要用d[i]表示i的第一个敌人,以后如果i有敌人那么他的d[i]一伙都是他的朋友
书上有道说谎岛的问题,很有意思,网上只有这http://bluegirl25.blog.163.com/blog/static/6391729720095105329160/描述得完整些
给出n句话,每句话有两个问题的回答,要么是对要么是错,回答一真一假,合并两种情况.最后,如果一个问题的回答对与错在同一个集合内就自相矛盾,no answer.否则,会有n个两两对立的情况,也就是在n/2种情况中要么选这要么选那,答案是2^(连通块个数/2)
并查集的题目还不少,poj上的资源很丰富,食物链等经典题目也是要做的.今天只是几道水题罢了,以后应该要再做不少才能熟练掌握并灵活运用.