zoj 1203 Swordfish【MST】

题目连接 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;
}

  

posted @ 2012-11-09 14:52  小猴子、  阅读(706)  评论(0编辑  收藏  举报