并查集例子

来源:互联网 发布:网络病毒的危害 编辑:程序博客网 时间:2024/05/16 16:13

2.并查集算法以及路径压缩

[置顶] 并查集详解 (转)

 

来自<http://blog.csdn.net/dellaserss/article/details/7724401>

 

 

【转】并查集算法和路径压缩

 

来自<http://www.cnblogs.com/TonyNeal/p/bingchaji.html>

 

int pre[1000 ];

int find(intx)                                                                                                      //查找根节点

   int r=x;

   while ( pre[r ] != r)                                                                                             //返回根节点 r

          r=pre[r];

 

   int i=x , j ;

   while( i != r)                                                                                                      //路径压缩

   {

        j = pre[ i ]; // 在改变上级之前用临时变量  j 记录下他的值 

        pre[ i ]= r ; //把上级改为根节点

        i=j;

   }

   return r ;

}

 

void join(intx,inty)                                                                                                    //判断x y是否连通,

                                                                                            //如果已经连通,就不用管了 //如果不连通,就把它们所在的连通分支合并起,

{

   int fx=find(x),fy=find(y);

   if(fx!=fy)

       pre[fx ]=fy;//接通需要通过两个父节点进行连接  pre【fx】=fy; 意思是fx的父节点为fy

}

代码:

//本程序的本质就是查询存在的连接数  通过总数减去存在的 得到的就是需要增加的最小连接数

#include<iostream>

using namespace std;

int n,m,a,b;

int sum,pre[10000];

 

int find(int x)

{

intr;

r=x;

while(pre[r]!=r)

{

r=pre[r];

}

inti=x,j;

while(i!=r)

{

j=pre[i];//¼Ç¼ֵ

pre[i]=r;

i=j;

}

returnr;

}

 

void join(int x,inty)

{

intfx=find(x),fy=find(y);

if(fx!=fy)

{

pre[fx]=fy;

sum--;

}

}

int main()

{

while(cin>>n&&n)

{

cin>>m;

sum=n-1;

for(inti=1;i<=n;i++)//³õʼ»¯Á¬½Óµã

pre[i]=i;

for(inti=1;i<=m;i++)

{

cin>>a>>b;

join(a,b);

}

cout<<sum<<endl;

}

return0;

}