您的位置:首页 > 编程语言 > Go语言

Algorithm --> 并查集

2015-08-02 21:43 429 查看
[b]并查集[/b]

主要解决图的连通性问题,比如:

  1、随意给你两个点,让你判断它们是否连通;

  2、问你整幅图一共有几个连通分支;

初始化:

void init(int size)
{
for(int i = 0; i < size; i++) pre[i] = i;
}


代码(非递归):

int find(int x)           //查找根节点
{
int r = x;
while(pre[r] != r) r =  pre[r];    //返回根节点 r

int i = x , j ;
while(i != r)     //路径压缩
{
j = pre[i];   // 在改变上级之前用临时变量  j 记录下他的值
pre[i] = r ;  //把上级改为根节点
i = j;
}
return r ;
}

void join(int x,int y)     //判断x y是否连通
{
int fx = find(x);
int fy = find(y);

if(fx != fy)    //如果已经连通,就不用管了; 如果不连通,就把它们所在的连通分支合并起
pre[fx]=fy;
}


递归法:

int find(int x)
{
if (x != pre[x])
pre[x] = find(pre[x]);

return pre[x];
}


求连接非连通图,需要几条边:

#include <iostream>
using namespace std;

int N, E, Answer;
int pre[1000];

int find(int x)
{
int r = x;

while(pre[r] != r)   //找父亲
r = pre[r];

int i = x, j;
while(i != r)   //路径压缩
{
j = pre[i];
pre[i] = r;
i = j;
}

return r;
}

int find2(int x)   //递归
{
if (x != pre[x])
pre[x] = find(pre[x]);

return pre[x];
}

int main()
{
int x, y, p1, p2;
while(cin >> N, N)         //顶点数
{
Answer = N-1;  //N个顶点需要N-1条边
for(int i = 1; i <= N; i++)
        pre[i] = i;   //每个顶点的父亲都是自己

cin >> E;   //边数
while(E--)
{
cin >> p1 >> p2;
x = find(p1);
y = find(p2);

if(x != y) //如果是不连通的,把这两个分支连起来, 分支的总数就减少了1,还需建的路也就减了1
{
pre[y]=x;
Answer--;
}
//如果两点已经连通了,那么这条路只是在图上增加了一个环 //对连通性没有任何影响,无视掉
}
cout << Answer << endl; //最后输出还要修的路条数
}
}


输入:

4 2
1 2
3 4

7 5
1 2
2 3
3 4
1 5
6 7
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: