PAT-Top1001. Battle Over Cities - Hard Version (35)
Posted 王景迁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
参考资料
以上是关于PAT-Top1001. Battle Over Cities - Hard Version (35)的主要内容,如果未能解决你的问题,请参考以下文章
pat 顶级 1001 Battle Over Cities - Hard Version (35 分)
PAT顶1001 Battle Over Cities - Hard Version (35 分) Kruskal求最小生成树
PAT T1001 Battle Over Cities-Hard Version
pat1001. Battle Over Cities - Hard Version 解题报告