题目连接 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=203
题目描述:
给定平面上N个城市的位置,计算连接这N个城市所需线路长度总和的最小值。
输入描述:
输入文件中包含多个测试数据。每个测试数据的第1行为一个正整数N,0《=N《=100,代表需要连接的城市数目;接下来有N行,每行为两个实数X和Y,-10000《=X,Y《=10000,表示每个城市的X坐标和Y坐标。输入文件中最后一行为N=0,代表输入结束。
输出描述:
对输入文件中每个测试数据,计算连接所有城市所需线路长度总和的最小值。每对城市之间的线路为连接这两个城市的直线。对于求得的值精确到小数点后两位有效数字。
代码:
//MST
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define MAXN 5000
int m, n; //n个点,m个边
int parent[101];
double x[101], y[101], ans;
struct E {
int u, v;
double w;
};
struct E edge[MAXN];
int cmp(const void *a, const void *b)
{
struct E c = *(struct E*)a;
struct E d = *(struct E*)b;
if(c.w > d.w) return 1;
return -1;
}
int Find(int x)
{
int s = x;
while( parent[s] >= 0 ) {
s = parent[s];
}
while( s != x ) {
int tmp = parent[x];
parent[x] = s;
x = tmp;
}
return s;
}
int Union(int R1, int R2)
{
int r1 = Find(R1);
int r2 = Find(R2);
if(r1 == r2) return 0;
int tmp = parent[r1] + parent[r2];
if(parent[r1] > parent[r2]) {
parent[r1] = r2;
parent[r2] = tmp;
} else {
parent[r2] = r1;
parent[r1] = tmp;
}
return 1;
}
void Kruskal()
{
int num = 0;
for(int i = 0; i < m; i++) {
if(Union(edge[i].u, edge[i].v)) {
ans += edge[i].w;
num++;
}
if(num >= n-1) break;
}
}
int main()
{
int T = 0;
while(scanf("%d", &n), n) {
ans = 0;
for(int i = 0; i < n; i++) {
scanf("%lf %lf", &x[i], &y[i]);
}
m = 0;
for(int i = 0; i < n; i++) {
for(int j = i+1; j < n; j++) {
edge[m].u = i;
edge[m].v = j;
edge[m].w = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
m++;
}
}
qsort(edge, m, sizeof(struct E), cmp);
memset(parent, -1, sizeof(parent));
Kruskal();
if( T ) printf("\n");
printf("Case #%d:\n", ++T);
printf("The minimal distance is: %.2lf\n", ans);
}
return 0;
}