标签:技术分享 列表 kruskal算法 有序 scanf space while return mini
在敌人占领之前由城市和公路构成的图是连通图。在敌人占领某个城市之后所有通往这个城市的公路就会被破坏,接下来可能需要修复一些其他被毁坏的公路使得剩下的城市能够互通。修复的代价越大,意味着这个城市越重要。如果剩下的城市无法互通,则说明代价无限大,这个城市至关重要。最后输出的是代价最大的城市序号有序列表。借助并查集和Kruskal算法(最小生成树算法)来解决这个问题。
1 //#include "stdafx.h" 2 #include <iostream> 3 #include <algorithm> 4 #include <vector> 5 6 using namespace std; 7 8 struct edge { // edge struct 9 int u, v, cost; 10 }; 11 vector<edge> edges; // the number of edges is greater than 500 far and away 12 13 int cmp(edge a, edge b) { // sort rule 14 return a.cost < b.cost; 15 } 16 17 int parent[510]; // union-find set 18 19 void initParent(int n) { // initialize union-find set 20 int i; 21 for(i = 1; i <= n; i++) { 22 parent[i] = -1; // a minus means it is a root node and its absolute value represents the number of the set 23 } 24 } 25 26 int findRoot(int x) { // find the root of the set 27 int s = x; 28 while(parent[s] > 0) { 29 s = parent[s]; 30 } 31 32 int temp; 33 while(s != x) { // compress paths for fast lookup 34 temp = parent[x]; 35 parent[x] = s; 36 x = temp; 37 } 38 39 return s; 40 } 41 42 void unionSet(int r1, int r2) { // union sets. More concretely, merge a small number of set into a large collection 43 int sum = parent[r1] + parent[r2]; 44 if(parent[r1] > parent[r2]) { 45 parent[r1] = r2; 46 parent[r2] = sum; 47 } else { 48 parent[r2] = r1; 49 parent[r1] = sum; 50 } 51 } 52 53 int maxw = 1; // max cost 54 bool infw; // infinite cost 55 56 int kruskal(int n, int m, int out) { // Kruskal algorithm to get minimum spanning tree 57 initParent(n); 58 59 int u, v, r1, r2, num = 0, i, w = 0; 60 for (i = 0; i < m; i++) { 61 u = edges[i].u; 62 v = edges[i].v; 63 64 if (u == out || v == out) { 65 continue; 66 } 67 68 r1 = findRoot(u); 69 r2 = findRoot(v); 70 71 if (r1 != r2) { 72 unionSet(r1, r2); 73 num++; 74 75 if (edges[i].cost > 0) { // only consider the cost which is not zero 76 w += edges[i].cost; 77 } 78 79 if (num == n - 2) { 80 break; 81 } 82 } 83 } 84 85 //printf("num %d\n", num); 86 if (num < n - 2) { // spanning tree is not connected 87 w = -1; // distinguish the situation of the occurrence of infinite cost 88 89 if (!infw) { // when infinite cost first comes out 90 infw = true; 91 } 92 } 93 94 return w; 95 } 96 97 int main() { 98 int n, m; 99 scanf("%d%d", &n, &m); 100 101 int i, status; 102 edge e; 103 for (i = 0; i < m; i++) { 104 scanf("%d%d%d%d", &e.u, &e.v, &e.cost, &status); 105 if (status == 1) { 106 e.cost = 0; 107 } 108 109 edges.push_back(e); 110 } 111 112 if (m > 0) { 113 sort(edges.begin(), edges.end(), cmp); 114 } 115 116 int curw, res[510], index = 0; 117 for (i = 1; i <= n; i++) { // traverse all vertices to obtain the target vertex 118 curw = kruskal(n, m, i); 119 if (!infw) { // when infinite cost doesn‘t come out 120 if (curw < maxw) { 121 continue; 122 } 123 124 if (curw > maxw) { 125 index = 0; 126 maxw = curw; 127 } 128 res[index++] = i; 129 } else { // otherwise 130 if (curw < 0) { 131 if (maxw > 0) { 132 maxw = -1; 133 index = 0; 134 } 135 136 res[index++] = i; 137 } 138 } 139 } 140 141 if (index > 0) { 142 for (i = 0; i < index; i++) { 143 if (i > 0) { 144 printf(" "); 145 } 146 printf("%d", res[i]); 147 } 148 } else { 149 printf("0"); 150 } 151 printf("\n"); 152 153 system("pause"); 154 return 0; 155 }
参考资料
pat-top 1001. Battle Over Cities - Hard Version (35)
PAT-Top1001. Battle Over Cities - Hard Version (35)
标签:技术分享 列表 kruskal算法 有序 scanf space while return mini
原文地址:http://www.cnblogs.com/WJQ2017/p/7568268.html