超级传送门:
http://acm.hdu.edu.cn/showproblem.php?pid=1233
题目大意:
给出N个点之间的距离,要求建公路让N个点互相可达,求公路最短的长度。
题目分析:
由题目意思可得这一题是最小生成树的问题
下面用Kruskal的实现了一下,Kruskal的大致方法:
从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中
不会产生环路 的大致方法:
并查集!!!
#include<iostream>
using namespace std;
struct node
{
int v1;
int v2;
int w;
};
int father[10000];
int cmp(const void *a,const void *b)
{
node c = *(node *)a;
node d = *(node *)b;
return c.w - d.w;
}
//初始化并查集
void Init()
{
for(int i = 0;i<10000;i++)
{
father[i] = i;
}
}
//寻找祖宗
int find(int x)
{
int root,temp;
temp = x;
while(father[x] != x)
{
x = father[x];
}
root = x;
x= temp;
while(father[x] != x)
{
temp = father[x];
father[x] = root;
x = temp;
}
return root;
}
int main()
{
int N;
int temp;
int a,b,c;
node p[10000];
int i,j;
int ans;
int r1,r2;
while(scanf("%d",&N) != EOF)
{
if(N == 0) break;
temp = N*(N-1)/2;
for(i=0;i<temp;i++)
{
scanf("%d %d %d",&a,&b,&c);
p[i].v1 = a;
p[i].v2 = b;
p[i].w = c;
}
//kruskal三部曲
//1.排序
qsort(p,temp,sizeof(p[0]),cmp);
Init();
ans = 0;
//2 从小到大拿出来
for(i=0;i<temp;i++)
{
//3 判断有没有环
r1 = find(p[i].v1);
r2 = find(p[i].v2);
//没环就加进去
if(r1 != r2)
{
ans += p[i].w;
father[r1] = r2;
}
}
printf("%d\n",ans);
}
return 0;
}