浅谈并查集

      最近几天学习了并查集。并查集干的无非就是两件事:并和查。当然在查的时候要进行路径压缩,这个我之后会说。

      首先很感谢这个例子,让我明白了并查集实质是什么。

      下面就来看这个例子:

      话说江湖上散落着各式各样的大侠,有上千个之多。他们没有什么正当职业,整天背着剑在外面走来走去,碰到和自己不是一路人的,就免不了要打一架。但 大侠们有一个优点就是讲义气,绝对不打自己的朋友。而且他们信奉“朋友的朋友就是我的朋友”,只要是能通过朋友关系串联起来的,不管拐了多少个弯,都认为 是自己人。这样一来,江湖上就形成了一个一个的群落,通过两两之间的朋友关系串联起来。而不在同一个群落的人,无论如何都无法通过朋友关系连起来,于是就 可以放心往死了打。但是两个原本互不相识的人,如何判断是否属于一个朋友圈呢?我们可以在每个朋友圈内推举出一个比较有名望的人,作为该圈子的代表人物, 这样,每个圈子就可以这样命名“齐达内朋友之队”“罗纳尔多朋友之队”……两人只要互相对一下自己的队长是不是同一个人,就可以确定敌友关系了。


      但是还有问题啊,大侠们只知道自己直接的朋友是谁,很多人压根就不认识队长,要判断自己的队长是谁,只能漫无目的的通过朋友的朋友关系问下去:“你是不是 队长?你是不是队长?”这样一来,队长面子上挂不住了,而且效率太低,还有可能陷入无限循环中。于是队长下令,重新组队。队内所有人实行分等级制度,形成 树状结构,我队长就是根节点,下面分别是二级队员、三级队员。每个人只要记住自己的上级是谁就行了。遇到判断敌友的时候,只要一层层向上问,直到最高层, 就可以在短时间内确定队长是谁了。由于我们关心的只是两个人之间是否连通,至于他们是如何连通的,以及每个圈子内部的结构是怎样的,甚至队长是谁,并不重 要。所以我们可以放任队长随意重新组队,只要不搞错敌友关系就好了。于是,门派产生了。

      好的,现在已经搞清楚并查集是什么了,那么要怎么具体实现呢?

      先说查吧:

1 int find (int a){
2       if(father[a]!=a){
3             father[a]=find(father[a]); //一直递归直到找到根节点
4       }
5     return a;
6 }        

      接下来是并:

1 int link (int a ,int b){
2         int x=find(a);//找到a的根节点
3         int y=find(b);//找到b的根节点
4         if(x!=y)  //a,b的根节点不是同一个
5             father[y]=x; //把b的根节点连接到a上
6 
7 }            

 

 

posted @ 2013-08-05 14:51  小の泽  阅读(178)  评论(0编辑  收藏  举报