并查集分析+总结

对于并查集: 很多次都是迷迷糊糊,尤其是对并查集的优化:

1.路径压缩  2.按秩合并

对此个人整理了一下:

对于最基本的并查集建议看看: 

百度百科:  http://baike.baidu.com/view/521705.htm

以例题的形式分析,并用算法描述了

博客园:   对于有点基础的可以参考下,清晰明了

http://www.cnblogs.com/cherish_yimi/archive/2009/10/11/1580839.html

对于第二个优化按秩合并的部分处理有点异议:

if(rank[x] < rank[y])
              {
                  num[x]=y;
               
              }
              else if(rank[x]> rank[y])
              {
                  num[y]=x;
              }
              else rank[y]++;

看到很多博客上都是这么写的,就连维基百科上也是这么处理的!

个人感觉这样会大大使按秩合并的优化打折,这样处理应该比上面的哪个要严谨多了

           if(rank[x] <= rank[y])
              {
                  num[x]=y;
                  rank[y]+=rank[x];
              }
              else if(rank[x]> rank[y])
              {
                  num[y]=x;
                  rank[x]+=rank[y];
              }

而在sdutoj 2391测试  时间只是略快 

题目推荐:

poj 1611  The Suspects

http://poj.org/problem?id=1611

模版题不解释 

 

View Code
#include<stdio.h>
#include<string.h>
#define N 30005
int num[N];int rank[N];

int match(int n)
{
if(n!=num[n])
num[n]=match(num[n]);
return num[n];
}

int main()
{
int n,m,k;
while(scanf("%d%d",&n,&m),n+m)
{
//memset(rank,1,sizeof(rank));
for(int i=0;i<=n;i++)
{
num[i]=i; rank[i]=1;
}
while(m--)
{

int a,b,x,y;
scanf("%d%d",&k,&a);

for(int i=1;i<k;i++)
{
scanf("%d",&b);
x=match(a);y=match(b);
if( x!= y )
{
if(rank[x] <= rank[y])
{
num[x]=y;
rank[y]+=rank[x];
}
else
{
num[y]=x;
rank[x]+=rank[y];
}

}
}
}
printf("%d\n",rank[match(0)]);
}
}

sdut 2391  Dark roads

http://acm.sdut.edu.cn/web/problem.php?action=showproblem&problemid=2391

View Code
#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 200005
int n,m,road;
struct node
{
int s,e,cost;
}root[N];
int num[N];
int cmp(node a,node b)
{
return a.cost<b.cost;
}
int find(int x)
{
if(x!=num[x]) num[x]=find(num[x]);
return num[x];
}
void dijk()
{
for(int i=0;i<=n;i++) num[i]=i;
road=0;
for(int i=0;i<m;i++)
{
int x,y;
x=find(root[i].s);
y=find(root[i].e);
if(x!=y)
{
num[x]=y;
road+=root[i].cost;
} } }
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
int sum=0;
for(int i=0;i<m;i++)
{ int x,y,z;
scanf("%d%d%d",&x,&y,&z);
root[i].s=x;root[i].e=y;
root[i].cost=z; sum+=z;
}
sort(root,root+m,cmp);
dijk();
printf("%d\n",sum-road);
}
}


 以上纯属个人见解,望大家批评指正

posted @ 2012-03-02 19:53  skyming  阅读(1422)  评论(0编辑  收藏  举报