ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)
生活随笔
收集整理的這篇文章主要介紹了
ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
四道MST,適合Prim解法,也可以作為MST練習題。
題意包括在代碼中。
?
POJ1258-Agri Net
?
水題
1 //Prim-沒什么好說的 2 //接受一個鄰接矩陣,求MST 3 //Time:0Ms Memory:220K 4 #include<iostream> 5 #include<cstring> 6 #include<cstdio> 7 #include<algorithm> 8 using namespace std; 9 #define MAX 105 10 #define INF 0x3f3f3f3f 11 int n, m; 12 int d[MAX][MAX]; 13 int lowcost[MAX]; 14 bool v[MAX]; 15 void prim() 16 { 17 int minroad = 0; 18 memset(v, false, sizeof(v)); 19 v[0] = true; 20 for (int i = 1; i < n; i++) 21 lowcost[i] = d[i][0]; 22 for (int i = 1; i < n; i++) 23 { 24 double mind = INF; 25 int k; 26 for (int j = 1; j < n; j++) 27 { 28 if (!v[j] && mind > lowcost[j]) 29 { 30 mind = lowcost[j]; 31 k = j; 32 } 33 } 34 35 minroad += lowcost[k]; 36 v[k] = true; 37 for (int j = 1; j < n; j++) 38 if (!v[j]) lowcost[j] = min(d[k][j], lowcost[j]); 39 } 40 printf("%d\n", minroad); 41 } 42 int main() 43 { 44 while (scanf("%d", &n) != EOF) 45 { 46 for (int i = 0; i < n; i++) 47 for (int j = 0; j < n; j++) 48 scanf("%d", &d[i][j]); 49 prim(); 50 } 51 return 0; 52 }?
?
?
POJ1751(ZOJ2048)-Highways
?
1 //Prim-好題 2 //ZOJ2048-POJ1751 3 //ZOJ中多組樣例,兩個樣例間有一個空格(否則會WA) 4 //需要記錄上一個節點-注意內存限制在10^4K內 5 //有M個城市已經有通路,輸出讓N個城市生成最短通路的各邊,Special Judge-輸出次序不定 6 //Time:94Ms Memory:4648K 7 #include<iostream> 8 #include<cstring> 9 #include<cstdio> 10 #include<cmath> 11 #include<algorithm> 12 using namespace std; 13 14 #define MAX 755 15 #define INF 0x3f3f3f3f 16 #define POW2(x) ((x)*(x)) 17 #define DIS(i,j) (sqrt(POW2(p[i][0] - p[j][0]) + POW2(p[i][1] - p[j][1]))) 18 19 int n, m; 20 double p[MAX][2]; 21 int fa[MAX]; //記錄上一個頂點 22 double d[MAX][MAX]; 23 double lowcost[MAX]; 24 bool v[MAX]; 25 26 void prim() 27 { 28 memset(v, false, sizeof(v)); 29 v[1] = true; 30 for (int i = 2; i <= n; i++) 31 { 32 lowcost[i] = d[i][1]; 33 fa[i] = 1; 34 } 35 for (int i = 2; i <= n; i++) 36 { 37 double mind = INF; 38 int k; 39 for (int j = 2; j <= n; j++) 40 { 41 if (!v[j] && mind > lowcost[j]) 42 { 43 mind = lowcost[j]; 44 k = j; 45 } 46 } 47 if (mind > 1e-5) 48 printf("%d %d\n", fa[k], k); 49 50 v[k] = true; 51 for (int j = 2; j <= n; j++) 52 { 53 if (!v[j] && lowcost[j] > d[k][j]) 54 { 55 lowcost[j] = d[k][j]; 56 fa[j] = k; 57 } 58 } 59 } 60 } 61 62 int main() 63 { 64 scanf("%d", &n); 65 for (int i = 1; i <= n; i++) 66 { 67 scanf("%lf%lf", &p[i][0], &p[i][1]); 68 for (int j = 1; j < i; j++) 69 d[i][j] = d[j][i] = DIS(i, j); 70 } 71 scanf("%d", &m); 72 for (int i = 0; i < m; i++) 73 { 74 int v1, v2; 75 scanf("%d%d", &v1, &v2); 76 d[v1][v2] = d[v2][v1] = 0; 77 } 78 prim(); 79 return 0; 80 }?
?
POJ2349(ZOJ1914)-Arctic Network
?
1 //Prim 2 //POJ2349-ZOJ1914 3 //有n個前哨可以通過衛星通信(無距離限制),總共m個前哨,相互通信可以通過無線電通信(有距離限制),求所需無線電信號最短距離 4 //定理:如果去掉所有權值大于d的邊后,最小生成樹被分割成為k個連通支,圖也被分割成為k個連通支(可嘗試證明) 5 //Time:47Ms Memory:2164K 6 #include<iostream> 7 #include<cstring> 8 #include<cstdio> 9 #include<cmath> 10 #include<algorithm> 11 using namespace std; 12 13 #define MAX 501 14 #define INF 0x3f3f3f3f 15 #define POW2(x) ((x)*(x)) 16 #define DIS(i,j) (sqrt(POW2(p[i][0] - p[j][0]) + POW2(p[i][1] - p[j][1]))) 17 18 int n, m; 19 double p[MAX][2]; //point 20 double d[MAX][MAX]; //distance 21 double lowcost[MAX]; 22 bool v[MAX]; 23 24 void prim() 25 { 26 memset(lowcost, 0, sizeof(lowcost)); 27 memset(v, false, sizeof(v)); 28 v[0] = true; 29 for (int i = 1; i < m; i++) 30 lowcost[i] = d[i][0]; 31 for (int i = 1; i < m; i++) 32 { 33 int mind = INF; 34 int k; 35 for (int j = 1; j < m; j++) 36 { 37 if (!v[j] && mind > lowcost[j]) 38 { 39 mind = lowcost[j]; 40 k = j; 41 } 42 } 43 v[k] = true; 44 for (int j = 1; j < m; j++) 45 if(!v[j]) lowcost[j] = min(d[k][j], lowcost[j]); 46 } 47 } 48 49 int main() 50 { 51 int T; 52 scanf("%d", &T); 53 while (T--) 54 { 55 scanf("%d%d", &n, &m); 56 for (int i = 0; i < m; i++) 57 { 58 scanf("%lf%lf", &p[i][0], &p[i][1]); 59 for (int j = 0; j < i; j++) 60 d[i][j] = d[j][i] = DIS(i, j); 61 } 62 63 prim(); 64 sort(lowcost, lowcost + m); 65 printf("%.2lf\n", lowcost[m - n]); 66 //G++需要使用printf("%.2f\n", lowcost[m-n]); 67 //原因查了半天,好像是因為新版GCC標準中將%f和%lf合并為%f的意思 68 } 69 return 0; 70 }?
?
?
POJ3026-Borg Maze
?
1 //Prim+BFS 2 //總是心想著要創造一個新算法,結果越想越麻煩... 3 //保險做法:找出每個點間的距離,再進行Prim 4 //Time:79Ms Memory:292K 5 #include<iostream> 6 #include<cstring> 7 #include<cstdio> 8 #include<queue> 9 #include<algorithm> 10 using namespace std; 11 12 #define MAX 125 //MAX 50的話會RE或WA(博主在55RE,在100WA) 13 14 struct Point{ 15 int x, y; 16 int step; 17 }p; 18 19 int r, c; 20 char board[MAX][MAX]; 21 int d[MAX][MAX]; 22 int num[MAX][MAX], cnt; 23 int lowcost[MAX]; 24 bool v[MAX][MAX]; 25 int mov[4][2] = { {1,0}, {-1,0}, {0,1}, {0,-1} }; 26 27 void bfs(Point p) 28 { 29 memset(v, false, sizeof(v)); 30 v[p.x][p.y] = true; 31 int np = num[p.x][p.y]; 32 queue<Point> q; 33 p.step = 0; 34 q.push(p); 35 while (!q.empty()) 36 { 37 Point cur = q.front(); 38 q.pop(); 39 for (int i = 0; i < 4; i++) 40 { 41 Point t = cur; 42 t.x += mov[i][0]; 43 t.y += mov[i][1]; 44 if (t.x > 0 && t.y > 0 && t.x < r && t.y < c && !v[t.x][t.y]) 45 { 46 if (board[t.x][t.y] == '#') continue; 47 int nt = num[t.x][t.y]; 48 t.step++; 49 v[t.x][t.y] = true; 50 if (board[t.x][t.y] == 'A' || board[t.x][t.y] == 'S') 51 d[nt][np] = t.step; 52 q.push(t); 53 } 54 } 55 } 56 } 57 58 void prim() 59 { 60 int v[MAX]; 61 memset(v, false, sizeof(v)); 62 memset(lowcost, 0x3f, sizeof(lowcost)); 63 v[0] = true; 64 for (int i = 1; i < cnt; i++) 65 lowcost[i] = d[i][0]; 66 67 int minv = 0; 68 for (int i = 1; i < cnt; i++) 69 { 70 int mind = 0x3f3f3f3f; 71 int k; 72 for (int j = 1; j < cnt; j++) 73 { 74 if (!v[j] && mind > lowcost[j]) 75 { 76 mind = lowcost[j]; 77 k = j; 78 } 79 } 80 minv += mind; 81 v[k] = true; 82 for (int j = 1; j < cnt; j++) 83 if (!v[j]) lowcost[j] = min(lowcost[j], d[k][j]); 84 } 85 printf("%d\n", minv); 86 } 87 88 int main() 89 { 90 int T; 91 scanf("%d", &T); 92 while (T--) 93 { 94 cnt = 0; 95 scanf("%d%d", &c, &r); 96 gets_s(board[0]); 97 for (int i = 0; i < r; i++) 98 { 99 gets_s(board[i], MAX); 100 for (int j = 0; j < c; j++) 101 if (board[i][j] == 'S' || board[i][j] == 'A') 102 num[i][j] = cnt++; 103 } 104 for (int i = 0; i < r; i++) 105 for (int j = 0; j < c;j++) 106 if (board[i][j] == 'S' || board[i][j] == 'A') 107 { 108 p.x = i; p.y = j; 109 bfs(p); 110 } 111 prim(); 112 } 113 return 0; 114 }?
轉載于:https://www.cnblogs.com/Inkblots/p/5380599.html
總結
以上是生活随笔為你收集整理的ACM/ICPC 之 四道MST-Prim解法(POJ1258-POJ1751-POJ2349-POJ3026)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 160个crackme 008 Andr
- 下一篇: 南京师范大学汤国安教授《地理信息与人类生