并查集

来源:互联网 发布:知名的中文域名案例 编辑:程序博客网 时间:2024/05/12 01:09

并查集是一种提高空间效率和时间效率的手段。就是把有关系的个体合并成同一个集合。然后可以随便查找某个个体或者元素属于哪个集合。关键是如何合并,并查集为一种树状结构。刚开始,所有点的根就是自己,如有10个点。初始状况为root[i]=i;就是自己的根就是自己的意思。然后如果确定两个点有关系了,如2,和3。那么只要将其中一个的根接到另一个的根。例如将2的根变成3。那么root[2]=3;当查找2属于哪个集合就找root[2]就行了。当有另一个集合(5,6),并且6为根,当现在又有两个点2和5确定有关系的时候,那就找到2的根,5的根,把其中一个的根(这里假设2的根3)接到5的根(6)(root[3]=6)上就OK,然后找2属于哪个集合,2找到3,3又找到6(root[6]==6)就能判断2属于6这个集合。依此类推...直到所有有关系的点都组成一个集合。每个集合只有一个根。是根的条件是root[t]=t;当判断两个点是否为同一集合时候只要顺藤摸瓜找他他们各自的根是否相等就行了。

并查集题目。

poj

2524   朴素入门题  代码

1611  也是朴素的并查集。可以增加一个ans数组来保存每个集合的个数。当两个集合合并的时候例如b合并到a,那么找出他们的根root[a]和root[b]然后ans[root[a]]+=ans[root[b]]更新a集合的个数,最后ans[s]就是总嫌疑患者的个数。

1308  判断是否是一个树,只要判断是否每个点的根都相同,即只能有一个根就行了。注意可能存在有坏,那样在v的根是u,然后输入u的根是v,那样在找v的时候他会找到u然后找到自己,自己又去找u无限循环超时,加个判断if(find(u)==v)自己指向根 就不是树即可。

并查集优化方法:路径压缩

我们每找一个点的根 例如2的根是3,3的根是4,4的根是5,那么找2的根就要遍历几次才到根,路径压缩就是将2的根直接赋成5,使得找的时候一次就找到减少时间开销。路径压缩运用递归。找2的根的时候就将root[2]赋值成find(root[2])直到root[t]=t;代码:

路径压缩题目

poj 1988此题很需要技巧,压缩路径还会超时,技巧在于开两个数组sum_set,sum_up[i],sum_set记录i所在集合一共有多少个方块(要知道i的集合有多少个方块,首先找到i的根,就是集合最上面那个方块father_i,然后sum_set[father_i]即为该集合的方块个数),sum_up记录i的上方有多少个方块(即i到他的根之间有多少个方块,最上方那个方块就是i的根,),那么i下面的方块个数就是sum_set[father_i]-sum_up[i]-1(不包括自己),代码

 

2492  这题刚一想,好如果两个虫有关系我立马把他们合并成一个集合,但是怎么确定同一个集合里面的虫是异性还是同性呢?想了好几下,于是发现个规律,传递性,如果a和b存在相交,那么他们异性设他们距离为1,然后b和c相交,b和c距离为1,那么a和c距离为2,以此类推,设一个数组dis保存每个虫到根的距离,凡是两个点到他们集合的根的距离的和为偶数,那么他们就同性,单数就是异性,那么合并的时候将一个虫所在集合的根接到另一个集合的根,距离为多少?(自己画个图推下就行了)。

1703 和2492没什么两样 运用同样的传递思想

2236  没什么特别的。

1182 超级无敌经典并查集,其数学含量远高于程序含量,不会做,看报告也不懂,主要是那公式不知道怎么推出来的,以后有灵感再回来破它