武林风云录
在王者大陆上,存在着很多派系,大家各自有各自的领袖。不同门派的帅小伙没什么正经工作,在峡谷里面溜达,见面以后往往会在物理上打成一片,但是由于派系里面都是体面人,大家不会打朋友的朋友,而且大家都只知道自己的直接上级。比如木兰和凯的关系比较好,拉拢一伙人自成了一派,号称长城守卫军,有一天盾山看到了凯,由于互相不熟,两个就想比划比划,但是打之前,他们会先确定一下各自是否在一个派系,盾山问了一下上级守约,守约说自己的上级是花木兰且木兰没有上级了,盾山报出自己的最终上级是木兰,凯也报出来自己的上级是木兰。哎呀,原来是寄几人,失礼失礼。于是两个人收起了自己的家伙,一起双双把家还了。
不难看出,在上面的过程中,整个长城守卫军的结构可以看作是一个树形结构,每个成员与自己的直接上级相连,但是可以沿着关系找到最终上级。而如果双方的最终上级不一致的话会是什么请况呢,比较明显的是,这将是一个拥有多个连通分量的图。其中包括长城守卫军、稷下学院和魏蜀吴等阵营,他们共同组成了现在的王者关系图。对于不同阵营的两位帅小伙,我们更希望的是他们能够和谐相处,最直接的方式就是让其中某一个阵营的领袖加入另外一个阵营,比如曹老板好人妻,所以占了木兰,木兰的上级改成曹操,最后长城守卫军的成员和魏地帅小伙见面就和谐相处了,因为他们拥有相同的领袖—曹老板。当然这里合并的话,谁合并谁都没区别,效果相同,至少目前来说如此。
上面的过程中有两个比较重要的过程,一个是找上级的过程,一个是合并阵营的过程,这两个过程提取出一个词叫做并查集。并查集解决的问题就是这类关系套关系的问题。
那么下面的问题就是,怎么实现上面的过程呢。首先是直接上级,可以采用数组faction[maxN]
来存储,具体体现为,faction[i]=x
代表的意思就是i的直接上级是x,如果要查找到派系领袖,也就是最终上级,只需要加上一个简单的循环。
int faction[1005]; //描述节点之间派系的数组
//查找节点的祖先
int findAncestor(int x) {
while(faction[x] != x) { //查找X的最终上级
x = faction[x];
}
return x;
}
好了,查找的过程就解决了,那么合并阵营呢?其实这里更简单,直接找到两位帅小伙x、y的阵营领袖,分别是rootx、rooty。现在的话faction[rootx]==rooty
直接就能实现效果,此后原先x阵营的兄弟们的直接上级就变成了rooty,完整的合并函数如下。
//合并两个节点的派系
void unionFaction(int x, int y) {
int aneX = findAncestor(x);
int aneY = findAncestor(y);
//合并之
faction[aneX] = aneY;
}
是不是炒鸡简单!