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;
}