hdu_1233(最小生成树)

 
 这道题是昨天那道畅通工程的升级题,用了最小生成树的思想,我是参考白书上的kruskal
代码做了这道题 (PS:白书果然 是王道!)。首先并查集是必不可少的,将两点之间的连
线看成边,这次不仅要将并查集初始化,还要初始化边的序号,用数组r来存储边的序号,
题目要求有m=n*(n-1)/2条路。我们用u[i],v[i],w[i],分别表示两个端点的序号,以及
两点间的距离,然后根据w[i]给边间接排序(排序的对象是边的序号,而不是边的长度)。
下一步就是在所有集合由距离的小到 大连接起来。
 下面是代码:
#include<stdio.h>
#include<stdlib.h>
#define SIZE 10010

int p[105],u[SIZE],v[SIZE],w[SIZE],r[SIZE];
int n,m;
int find(int x)
{
return p[x] == x ? x : (p[x] =find(p[x]) );
}

int cmp(const void *_p,const void *_q) /* 间接排序函数*/
{
int *p=(int *)_p;
int *q=(int *)_q;
return w[*p]-w[*q];
}

int main()
{
int i,e,x,y,j,ans;
while(scanf("%d",&n) , n)
{
ans = 0;
m = n*(n-1)/2;
for(j = 0; j < m; j ++) /*输入村庄序号以及两者之间的距离*/
{
scanf("%d%d%d",&u[j],&v[j],&w[j]);
u[j]--;
v[j]--;
}
for( i = 0; i < n; i ++) p[i] = i; //初始化并查集
for( i = 0; i < m; i ++) r[i] = i; //初始化边序号
qsort(r,m,sizeof(r[0]),cmp); //给边排序
for( i = 0; i < m; i ++)
{
e = r[i]; x = find(u[e]); y = find(v[e]); //找出两个村庄所在集合编号


/*不在一个集合,但现在有连接则合并*/

if( x != y) {

ans += w[e]; //每当合并将二者之间的距离加上。
p[x] = y;
}
}
printf("%d\n",ans);
}
return 0;
}

当然可能有些样例i不用循环到m就已经将所有的集合连接起来了,但是到m也没关系,时间复杂度
并不高!我自己先把这个方法消化一下...     
        
    
        
    
   

你可能感兴趣的:(最小生成树)