1. 程式人生 > >PAT-Top1001. Battle Over Cities - Hard Version (35)

PAT-Top1001. Battle Over Cities - Hard Version (35)

target pri stream emp tel col 生成樹算法 name ces

  在敵人占領之前由城市和公路構成的圖是連通圖。在敵人占領某個城市之後所有通往這個城市的公路就會被破壞,接下來可能需要修復一些其他被毀壞的公路使得剩下的城市能夠互通。修復的代價越大,意味著這個城市越重要。如果剩下的城市無法互通,則說明代價無限大,這個城市至關重要。最後輸出的是代價最大的城市序號有序列表。借助並查集和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 }
View Code

技術分享

參考資料

pat-top 1001. Battle Over Cities - Hard Version (35)

PAT-Top1001. Battle Over Cities - Hard Version (35)