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 }
他坐在湖边,望向天空,她坐在对岸,盯着湖面