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; }