ACM/ICPC 之 Kruskal范例(POJ1128(ZOJ1083))
Posted GUARDIAN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM/ICPC 之 Kruskal范例(POJ1128(ZOJ1083))相关的知识,希望对你有一定的参考价值。
最小生成树范例,Kruskal解法-以边为主体扩展最小生成树,需要利用并查集。
ZOJ1203-Swordfish
题意:求n个给定平面坐标的城市中的一条平面距离上的最短路长(保留两位小数)
题解:这道题数据不是很大,用Kruskal和Prim等算法都能够做。
Kruskal的算法思路是以边为主体扩展结点,即先选取权值最少的边,将两个不连通的端点加入到同一集合中(使其连通),舍去该边,接着找权值次小的,以此类推...
如果两个端点连通,则直接舍去该边。
因此可以先将所有边依据权值大小排序后,然后依次查找即可,为了较快地表示两个端点连通(属于同一集合),需要用到并查集的路径压缩。
1 //剑鱼行动-Kruskal 2 //找出n个给定平面坐标的城市中的一条最短路长(保留两位小数) 3 //Time:0Ms Memory:432K 4 #include<iostream> 5 #include<cstring> 6 #include<cstdio> 7 #include<cmath> 8 #include<algorithm> 9 using namespace std; 10 11 #define MAX 101 12 #define POW2(x) ((x)*(x)) 13 14 struct City { 15 double x, y; 16 }c[MAX]; 17 18 struct Edge { 19 int u, v; //端点 20 double road; 21 friend bool operator < (Edge e1, Edge e2) { return e1.road < e2.road; } 22 }e[MAX*MAX]; 23 24 int n, m; 25 int fa[MAX]; 26 double minroad; 27 28 int Find(int x) 29 { 30 return fa[x] < 0? x : fa[x] = Find(fa[x]); //查根+路径压缩 31 } 32 33 //加权法则合并 34 void Union(int r1,int r2) 35 { 36 int num = fa[r1] + fa[r2]; //集合元素总数-以负数计数 37 if (fa[r1] > fa[r2]) //r2集合元素多 38 { 39 fa[r1] = r2; 40 fa[r2] = num; 41 } 42 else { //r1集合元素多 43 fa[r2] = r1; 44 fa[r1] = num; 45 } 46 } 47 48 void kruskal() 49 { 50 minroad = 0; 51 memset(fa, -1, sizeof(fa)); 52 int num = 0; //已用结点数 53 for (int i = 0; i < m; i++) 54 { 55 int r1 = Find(e[i].u); 56 int r2 = Find(e[i].v); 57 if (r1 == r2) continue; 58 minroad += e[i].road; 59 Union(r1, r2); 60 num++; 61 if (num == n - 1) break; 62 } 63 } 64 65 int main() 66 { 67 int cas = 0; 68 while (scanf("%d", &n), n) 69 { 70 for (int i = 0; i < n; i++) 71 scanf("%lf%lf", &c[i].x, &c[i].y); 72 73 m = 0; 74 for (int i = 0; i < n; i++) 75 for (int j = i + 1; j < n; j++) 76 { 77 double d = sqrt(POW2(c[i].x - c[j].x) + POW2(c[i].y - c[j].y)); 78 e[m].road = d; 79 e[m].u = i; 80 e[m++].v = j; 81 } 82 83 sort(e, e + m); 84 85 kruskal(); 86 if (cas) printf("\n"); //博主在此PE过= = 87 printf("Case #%d:\n", ++cas); 88 printf("The minimal distance is: %.2lf\n", minroad); 89 } 90 91 92 return 0; 93 }
以上是关于ACM/ICPC 之 Kruskal范例(POJ1128(ZOJ1083))的主要内容,如果未能解决你的问题,请参考以下文章
ACM/ICPC 之 欧拉回路两道(POJ1300-POJ1386)
ACM/ICPC 之 DP进阶(51Nod-1371(填数字))