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

  在敌人占领之前由城市和公路构成的图是连通图。在敌人占领某个城市之后所有通往这个城市的公路就会被破坏,接下来可能需要修复一些其他被毁坏的公路使得剩下的城市能够互通。修复的代价越大,意味着这个城市越重要。如果剩下的城市无法互通,则说明代价无限大,这个城市至关重要。最后输出的是代价最大的城市序号有序列表。借助并查集和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)

转载于:https://www.cnblogs.com/WJQ2017/p/7568268.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值