按照“kuangbin带飞”系列和《挑战程序设计竞赛》上给出的练习题进行练习的图论内容。题量比较大,所以只写题号和代码了。纯手撸了这几个题,基本的这几个算法可以说是完全掌握了。
poj1251 Jungle Roads 最小生成树 kruskal
题目链接:http://poj.org/problem?id=1251
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef struct Node { 23 int a; 24 int b; 25 int v; 26 friend bool operator < (Node a, Node b) { 27 return a.v > b.v; 28 } 29 }Node; 30 31 const int maxn = 20010; 32 int pre[maxn]; 33 int n, ans; 34 Node p; 35 priority_queue<Node> pq; 36 37 int find(int x) { 38 return x == pre[x] ? x : pre[x] = find(pre[x]); 39 } 40 41 bool unite(int x, int y) { 42 x = find(x); 43 y = find(y); 44 if (x != y) { 45 pre[y] = x; 46 return true; 47 } 48 return false; 49 } 50 inline void init() { 51 for (int i = 0; i < maxn; i++) { 52 pre[i] = i; 53 } 54 while (!pq.empty()) pq.pop(); 55 } 56 57 int main() { 58 // freopen("in", "r", stdin); 59 while (~scanf("%d", &n) && n) { 60 init(); 61 char a[2], b[2]; 62 int cnt = 0; 63 int m, v; 64 ans = 0; 65 n--; 66 for (int i = 0; i < n; i++) { 67 scanf("%s %d", &a, &m); 68 for (int i = 0; i < m; i++) { 69 scanf("%s %d", &b, &v); 70 p.a = a[0] - 'A'; 71 p.b = b[0] - 'A'; 72 p.v = v; 73 pq.push(p); 74 } 75 } 76 while (n) { 77 p = pq.top(); 78 pq.pop(); 79 if (unite(p.a, p.b)) { 80 n--; 81 ans += p.v; 82 } 83 } 84 printf("%d ", ans); 85 } 86 }
poj1258 Agri-Net 最小生成树 prim
题目链接:http://poj.org/problem?id=1258
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 const int inf = 0xffffff; 23 const int maxn = 111; 24 int d[maxn]; 25 int G[maxn][maxn]; 26 int vis[maxn]; 27 int n; 28 29 void init() { 30 memset(vis, 0, sizeof(vis)); 31 for(int i = 0; i <= n; i++) d[i] = inf; 32 } 33 34 int prim(int s) { 35 d[s] = 0; 36 for(int i = 0; i < n; i++) { 37 int u = -1; 38 for(int j = 0; j < n; j++) { 39 if(!vis[j] && (u == -1 || d[u] > d[j])) { 40 u = j; 41 } 42 } 43 vis[u] = 1; 44 for(int j = 0; j < n; j++) { 45 if(!vis[j]) { 46 d[j] = min(G[u][j], d[j]); 47 } 48 } 49 } 50 int sp = 0; 51 for(int i = 0; i < n; i++) { 52 sp += d[i]; 53 } 54 return sp; 55 } 56 57 int main() { 58 // freopen("in", "r", stdin); 59 while(~scanf("%d", &n)) { 60 init(); 61 for(int i = 0; i < n; i++) { 62 for(int j = 0; j < n; j++) { 63 scanf("%d", &G[i][j]); 64 } 65 } 66 printf("%d ", prim(0)); 67 } 68 }
poj1287 Networking 最小生成树 prim(重边)
题目链接:http://poj.org/problem?id=1287
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 const int maxn = 105; 23 const int inf = 0xffffff; 24 int d[maxn]; 25 int G[maxn][maxn]; 26 int vis[maxn]; 27 int n, m; //n:vertex m:edge 28 29 void init() { 30 memset(vis, 0, sizeof(vis)); 31 for(int i = 0; i <= n; i++) { 32 d[i] = inf; 33 for(int j = 0; j <= n; j++) { 34 G[i][j] = G[j][i] = inf; 35 } 36 G[i][i] = 0; 37 } 38 } 39 40 int prim(int start) { 41 d[start] = 0; 42 for(int i = 1; i <= n; i++) { 43 int u = -1; 44 for(int j = 1; j <= n; j++) { 45 if(!vis[j]) { 46 if(u == -1 || d[j] < d[u]) { 47 u = j; 48 } 49 } 50 } 51 vis[u] = 1; 52 for(int j = 1; j <= n; j++) { 53 if(!vis[j]) { 54 d[j] = min(G[u][j], d[j]); 55 } 56 } 57 } 58 int sp = 0; 59 for(int i = 1; i <= n; i++) { 60 sp += d[i]; 61 } 62 return sp; 63 } 64 65 int main() { 66 // freopen("in", "r", stdin); 67 int u, v, w; 68 while(~scanf("%d %d", &n, &m) && n) { 69 init(); 70 while(m--) { 71 scanf("%d %d %d", &u, &v, &w); 72 if(w < G[u][v]) { 73 G[u][v] = G[v][u] = w; 74 } 75 } 76 printf("%d ", prim(1)); 77 } 78 }
poj2349 Arctic Network 求最小生成树第s+1长的边
题目链接:http://poj.org/problem?id=2349
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef struct Point { 23 int x; 24 int y; 25 double r; 26 }Point; 27 28 bool cmp(Point x, Point y) { 29 return x.r < y.r; 30 } 31 32 const int maxn = 222222; 33 priority_queue<int> pq; 34 int n, s, p; 35 int x[maxn],y[maxn]; 36 double d[maxn]; 37 int pre[maxn]; 38 Point poi[maxn]; 39 40 void init() { 41 while(!pq.empty()) pq.pop(); 42 for(int i = 0; i <= maxn; i++) { 43 pre[i] = i; 44 } 45 } 46 47 int find(int x) { 48 return x == pre[x] ? x : pre[x] = find(pre[x]); 49 } 50 51 bool unite(int x, int y) { 52 x = find(x); 53 y = find(y); 54 if(x != y) { 55 pre[x] = y; 56 return 1; 57 } 58 return 0; 59 } 60 61 int main() { 62 // freopen("in", "r", stdin); 63 scanf("%d", &n); 64 while(n--) { 65 init(); 66 scanf("%d %d", &s, &p); 67 for(int i = 0; i < p; i++) { 68 scanf("%d %d", &x[i], &y[i]); 69 } 70 int cnt = 0; 71 for(int i = 0; i < p; i++) { 72 for(int j = i+1; j < p; j++) { 73 poi[cnt].x = i; 74 poi[cnt].y = j; 75 poi[cnt++].r = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); 76 } 77 } 78 sort(poi, poi+cnt, cmp); 79 int cur = 0; 80 for(int i = 0; i < cnt; i++) { 81 if(unite(poi[i].x, poi[i].y)) { 82 d[cur++] = poi[i].r; 83 } 84 } 85 printf("%.2f ", d[cur-s]); 86 } 87 }
poj2236 Wireless Network 并查集
题目链接:http://poj.org/problem?id=2236
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef struct Com { 23 int x; 24 int y; 25 }Com; 26 27 const int maxn = 20010; 28 int pre[maxn]; 29 int con[maxn]; 30 int n, d, m; 31 Com com[maxn]; 32 33 bool far(Com c1, Com c2) { 34 return (c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y)<=d*d; 35 } 36 37 int find(int x) { 38 return x == pre[x] ? x : pre[x] = find(pre[x]); 39 } 40 41 void unite(int x, int y) { 42 x = find(x); 43 y = find(y); 44 if(x != y) { 45 pre[y] = x; 46 } 47 } 48 inline void init() { 49 memset(con, 0, sizeof(con)); 50 for(int i = 0; i < maxn; i++) { 51 pre[i] = i; 52 } 53 m = 0; 54 } 55 56 int main() { 57 // freopen("in", "r", stdin); 58 int a, b; 59 char cmd[3]; 60 while(~scanf("%d %d", &n, &d)) { 61 init(); 62 for(int i = 1; i <= n; i++) { 63 scanf("%d %d", &com[i].x, &com[i].y); 64 } 65 while(~scanf("%s", cmd)) { 66 if(cmd[0] == 'S') { 67 scanf("%d %d", &a, &b); 68 if(find(a) == find(b)) printf("SUCCESS "); 69 else printf("FAIL "); 70 } 71 else { 72 scanf("%d", &a); 73 for(int i = 0; i < m; i++) { 74 if(far(com[a], com[con[i]])) { 75 unite(a, con[i]); 76 } 77 } 78 con[m++] = a; 79 } 80 } 81 } 82 return 0; 83 }
poj2387 Til the Cows Come Home 最短路(floyd不可)
题目链接:http://poj.org/problem?id=2387
1 // #include <algorithm> 2 // #include <iostream> 3 // #include <iomanip> 4 // #include <cstring> 5 // #include <climits> 6 // #include <complex> 7 // #include <fstream> 8 // #include <cassert> 9 // #include <cstdio> 10 // #include <bitset> 11 // #include <vector> 12 // #include <deque> 13 // #include <queue> 14 // #include <stack> 15 // #include <ctime> 16 // #include <set> 17 // #include <map> 18 // #include <cmath> 19 20 // using namespace std; 21 22 // const int maxn = 1111; 23 // const int inf = 0x7fffff; 24 // int n, m, u, v, w; 25 // int G[maxn][maxn]; 26 27 // int main() { 28 // // freopen("in", "r", stdin); 29 // while(~scanf("%d %d", &n, &m)) { 30 // for(int i = 1; i <= m; i++) { 31 // for(int j = 1; j <= m; j++) 32 // G[i][j] = G[j][i] = inf; 33 // G[i][i] = 0; 34 // } 35 // for(int i = 1; i <= n; i++) { 36 // scanf("%d %d %d", &u, &v, &w); 37 // if(G[u][v] > w) 38 // G[u][v] = G[v][u] = w; 39 // } 40 // for(int k = 1; k <= m; k++) { 41 // for(int i = 1; i <= m; i++) { 42 // for(int j = 1; j <= m; j++) { 43 // if(G[i][j] > G[i][k] + G[k][j]) { 44 // G[i][j] = G[i][k] + G[k][j]; 45 // } 46 // } 47 // } 48 // } 49 // printf("%d ", G[1][m]); 50 // } 51 // } 52 53 54 55 #include <algorithm> 56 #include <iostream> 57 #include <iomanip> 58 #include <cstring> 59 #include <climits> 60 #include <complex> 61 #include <fstream> 62 #include <cassert> 63 #include <cstdio> 64 #include <bitset> 65 #include <vector> 66 #include <deque> 67 #include <queue> 68 #include <stack> 69 #include <ctime> 70 #include <set> 71 #include <map> 72 #include <cmath> 73 74 using namespace std; 75 76 const int maxn = 1111; 77 const int inf = 0x7fffff; 78 int d[maxn]; 79 int G[maxn][maxn]; 80 int vis[maxn]; 81 int n, m, u, v, w; 82 83 void init() { 84 memset(vis, 0, sizeof(vis)); 85 for(int i = 0; i <= m; i++) { 86 d[i] = inf; 87 for(int j = 0; j <= m; j++) { 88 G[i][j] = G[j][i] = inf; 89 } 90 G[i][i] = 0; 91 } 92 } 93 94 void dijkstra(int start) { 95 d[start] = 0; 96 for(int i = 1; i <= m; i++) { 97 int u = -1; 98 for(int j = 1; j <= m; j++) { 99 if(!vis[j]) { 100 if(u == -1 || d[j] < d[u]) { 101 u = j; 102 } 103 } 104 } 105 vis[u] = 1; 106 for(int j = 1; j <= m; j++) { 107 if(!vis[j]) { 108 d[j] = min(d[u]+G[u][j], d[j]); 109 } 110 } 111 } 112 } 113 114 int main() { 115 // freopen("in", "r", stdin); 116 while(~scanf("%d %d", &n, &m)) { 117 init(); 118 for(int i = 1; i <= n; i++) { 119 scanf("%d %d %d", &u, &v, &w); 120 if(G[u][v] > w) 121 G[u][v] = G[v][u] = w; 122 } 123 dijkstra(1); 124 printf("%d ", d[m]); 125 } 126 }
poj3268 Silver Cow Party 最短路(两边dijkstra)
题目链接:http://poj.org/problem?id=3268
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <cmath> 18 19 using namespace std; 20 21 22 const int maxn = 1001; 23 const int inf = 0x7ffffff; 24 int G[maxn][maxn]; 25 int d[maxn]; 26 int vis[maxn]; 27 int b[maxn]; 28 int s,e,v; 29 int n,m,i,j,x; 30 31 int findMin(int n) { 32 int minNode = 0; 33 int min = inf; 34 for(int i = 1;i <= n;i++) 35 if(!vis[i] && d[i] < min) { 36 minNode = i; 37 min = d[i]; 38 } 39 return minNode; 40 } 41 42 43 void dijkstra(int n,int x) { 44 int i,vnum; 45 memset(vis,false,sizeof(vis)); 46 for(i = 1;i <= n;i++) { 47 d[i] = G[x][i]; 48 } 49 vis[x] = 1; 50 vnum = 1; 51 while(vnum < n) { 52 int x = findMin(n); 53 if(x) { 54 vis[x] = 1; 55 vnum++; 56 for(i = 1; i <= n; i++) 57 if(!vis[i] && d[x] + G[x][i] < d[i]) 58 d[i] = G[x][i] + d[x]; 59 } 60 else break; 61 } 62 } 63 64 int findMax(int n) { 65 int max = 0; 66 for(int i = 1; i <= n; i++) 67 if(max < b[i]) max = b[i]; 68 return max; 69 } 70 71 72 void init(int n) { 73 for(int i = 0; i <= n; i++) { 74 b[i] = 0; 75 for(int j = 0; j <= n; j++) { 76 G[i][j] = inf; 77 } 78 } 79 memset(vis, false, sizeof(vis)); 80 81 } 82 83 int main() { 84 // freopen("in", "r", stdin); 85 scanf("%d %d %d", &n, &m, &x); 86 init(n); 87 for(i = 0;i < m;i++) { 88 scanf("%d %d %d",&s, &e, &v); 89 G[s][e] = v; 90 } 91 dijkstra(n,x); 92 for(i = 1;i <= n;i++) { 93 d[i] != inf ? b[i] = d[i] : b[i] = b[i]; 94 } 95 for(i = 1;i <= n;i++) { 96 for(j = i;j <= n;j++) { 97 G[i][j] = G[i][j] ^ G[j][i]; 98 G[j][i] = G[i][j] ^ G[j][i]; 99 G[i][j] = G[i][j] ^ G[j][i]; 100 } 101 } 102 dijkstra(n,x); 103 for(i = 1;i <= n;i++) { 104 d[i] != inf ? b[i] += d[i] : b[i] = b[i]; 105 } 106 printf("%d ", findMax(n)); 107 return 0; 108 }
邻接表,优先队列优化做法:
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef pair<int, int> PII; 23 const int inf = 100010; 24 const int maxn = 1111; 25 26 typedef struct Edge { 27 int v; 28 int w; 29 Edge(int vv, int ww) : v(vv), w(ww) {} 30 }; 31 32 vector<Edge> G1[maxn], G2[maxn]; 33 int n, m, x; 34 int u, v, w; 35 int d1[maxn], d2[maxn]; 36 int ans; 37 38 void dijkstra(int s, vector<Edge>* G, int* d) { 39 priority_queue<PII, vector<PII>, greater<PII> > pq; 40 for(int i = 1; i <= n; i++) d[i] = inf; 41 d[s] = 0; 42 pq.push(PII(0, s)); 43 while(!pq.empty()) { 44 PII p = pq.top(); pq.pop(); 45 int v = p.second; 46 if(d[v] < p.first) continue; 47 for(int i = 0; i < G[v].size(); i++) { 48 if(d[G[v][i].v] > d[v] + G[v][i].w) { 49 d[G[v][i].v] = d[v] + G[v][i].w; 50 pq.push(PII(d[G[v][i].v], G[v][i].v)); 51 } 52 } 53 } 54 } 55 56 int main() { 57 // freopen("in", "r", stdin); 58 scanf("%d %d %d", &n, &m, &x); 59 for(int i = 0; i < m; i++) { 60 scanf("%d %d %d", &u, &v, &w); 61 G1[u].push_back(Edge(v, w)); 62 } 63 dijkstra(x, G1, d1); 64 for(int i = 1; i <= n; i++) { 65 for(int j = 0; j < G1[i].size(); j++) { 66 G2[G1[i][j].v].push_back(Edge(i, G1[i][j].w)); 67 } 68 } 69 dijkstra(x, G2, d2); 70 ans = 0; 71 for(int i = 2; i <= n; i++) { 72 if(i == x) continue; 73 ans = max(ans, d1[i]+d2[i]); 74 } 75 printf("%d ", ans); 76 return 0; 77 }
hdoj1875 畅通工程再续 最小生成树(注意精度)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1875
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 typedef struct Point { 23 int x; 24 int y; 25 double r; 26 }Point; 27 28 int cmp(Point x, Point y) { 29 return x.r < y.r; 30 } 31 32 const int maxn = 10000; 33 int pre[maxn]; 34 int x[maxn]; 35 int y[maxn]; 36 int c, cnt; 37 Point poi[maxn]; 38 39 int find(int x) { 40 int r = x; 41 int t; 42 while(x != pre[x]) 43 x = pre[x]; 44 while(r != x) { 45 t = pre[r]; 46 pre[r] = x; 47 r = t; 48 } 49 return x; 50 } 51 52 void unite(int x, int y) { 53 int xx = find(x); 54 int yy = find(y); 55 if(xx != yy) { 56 pre[xx] = yy; 57 } 58 } 59 60 void init() { 61 for(int i = 0; i <= c; i++) { 62 pre[i] = i; 63 } 64 } 65 66 int main() { 67 // freopen("in", "r", stdin); 68 int T; 69 scanf("%d", &T); 70 while(T--) { 71 scanf("%d", &c); 72 cnt = 0; 73 for(int i = 0; i < c; i++) { 74 scanf("%d %d", &x[i], &y[i]); 75 } 76 for(int i = 0; i < c-1; i++) { 77 for(int j = i+1; j < c; j++) { 78 double rr = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); 79 poi[cnt].x = i; 80 poi[cnt].y = j; 81 poi[cnt++].r = rr; 82 } 83 } 84 init(); 85 sort(poi, poi+cnt, cmp); 86 double ans = 0; 87 for(int i = 0; i < cnt; i++) { 88 if(find(poi[i].x != find(poi[i].y)) && poi[i].r >= 10.0000 && poi[i].r <= 1000.00001) { 89 unite(poi[i].x, poi[i].y); 90 ans += poi[i].r; 91 } 92 } 93 // for(int i = 0; i < c; i++) printf("%d ", pre[i]); 94 // printf(" "); 95 int flag = 1; 96 int s = 0; 97 for(int i = 0; i < c; i++) { 98 if(pre[i] == i) { 99 s++; 100 } 101 if(s > 1) { 102 flag = 0; 103 break; 104 } 105 } 106 if(flag) printf("%.1lf ", ans * 100); 107 else printf("oh! "); 108 } 109 return 0; 110 }