建议你画个图理解下会容易很多。
先说下合并函数中的关系,因为在合并函数之前先进行了查找函数,而在查找函数中已压缩了路径,即把查找的点到根结点路径上所有点都挂到了根结点下,并更新了它们kind的值,保证kind值是正确的(在这之前是不正确的);所以在合并函数中x,y,rootx,rooty的kind值在它们原先的集合中都是正确的,在合并时,要将rooty挂到rootx上,并只更新rooty的kind值以保证rooty在新的集合中kind值正确,而不必管rooty原先集合的其它结点kind值(没法管,因为并查集只能从叶节点遍历到根结点,无法向下遍历,将会放到find函数中更新)。更新的依据是三个关系:x和y的关系,x和rootx关系,y和rooty关系;对于这题就一定能得到rootx和rooty的关系,以更新对rooty在新的集合中的kind值。
如果你能理解了合并函数,那查找函数便可以推得,因为我们合并时只更新了挂在根结点上的原先集合根结点的kind值,所以这里要把查找路径上所有的点先挂到根结点上,并更新其kind值(也就是每个集合深度为1的结点的kind值都是正确的)。更新顺序一定要是从深度低的到深度高的,因为更新依据要依赖当前结点的原kind值和其父节点的更新后的kind值。为什么是上述给出的两个值的和的关系呢?因为在合并前根结点的kind都为0,所以合并后原被合并集合深度为1的点的kind值只要加上更新后原其根结点的kind值就能得到正确关系了。一定要画图理解,模拟下过程,结合我红色标识的三个式子一起理解。我还有篇总结也许有帮助
http://www.cppblog.com/tortoisewu/archive/2009/05/29/86110.html@whr