-
Notifications
You must be signed in to change notification settings - Fork 0
/
uva10480_sabotage.cpp
168 lines (134 loc) · 4.15 KB
/
uva10480_sabotage.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
* This is a straight forward max flow - min cut problem.
* We traverse through the graph and each time send the
* minimum capacity flow through the path from source to target
* until we cannot send more.
* We then output the cut-set, i.e. the edges which are connecting
* from S-component to T-component.
*/
#include <bits/stdc++.h>
using namespace std;
#define V 51
bool visited[V];
int n;
int rGraph[V][V];
struct edge {
int from;
int to;
};
void print_graph() {
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++)
printf("%3d ", rGraph[i][j]);
cout << endl;
}
cout << endl;
}
void print_parent(int parent[]) {
for (int i=0; i<n; i++)
cout << parent[i] << " ";
cout << endl;
}
/*
* Simple breadth first search to find a path from source
* to target node, such that a flow can be sent across.
*
* @param s the source vertex
* @param t the target vertex
* @param parent the path to be populated.
*
* @return boolean value representing whether a flow can be
* sent across s and t.
*/
bool bfs(int s, int t, int parent[]) {
memset(visited, 0, sizeof(bool)*n);
queue<int> q;
q.push(s);
visited[s] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v=0; v<n; v++) {
if (!visited[v] && rGraph[u][v] > 0) {
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
return visited[t];
}
/*
* This function will do breadth first search, and on each iteration
* it will find the minimum capacity of a pipe(edge) connecting source to target.
* It will send a flow equal to the minimum capacity. It will repeat the steps until
* it cannot reach from source to target.
*
* forFulkerson(int graph[][], int s, int t)
* @param graph[][] the graph formed from uniform bidirectional flow from given edges
* @param s the source vertex
* @param t the target vertex
*
* @return the maximum flow that can be passed through the network.
*/
int fordFulkerson(int graph[V][V], int s, int t) {
int parent[n];
int max_flow = 0;
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
rGraph[i][j] = graph[i][j];
while (bfs(s, t, parent)) {
int minCapacity = INT_MAX;
// print_parent(parent);
// print_graph();
for (int v=t; v!=s; v=parent[v]) {
int u = parent[v];
if (minCapacity > rGraph[u][v]) {
minCapacity = rGraph[u][v];
}
}
// cout << minCapacity << endl;
for (int v=t; v!=s; v=parent[v]) {
int u = parent[v];
rGraph[u][v] -= minCapacity;
rGraph[v][u] += minCapacity;
}
max_flow += minCapacity;
}
// print_graph();
return max_flow;
}
int main() {
#ifndef ONLINE_JUDGE
// open the file in respective mode and redirect
// stream into respective file
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif // if ONLINE_JUDGE
int links;
int u, v, cap;
int graph[V][V];
int s = 0, t = 1;
while (cin >> n >> links && (n||links)) {
struct edge e[links];
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
graph[i][j] = 0;
for (int i=0; i<links; i++) {
cin >> u >> v >> cap;
e[i].from=u, e[i].to=v;
graph[u-1][v-1] = graph[v-1][u-1] = cap;
}
fordFulkerson(graph, s, t);
int parent[n];
memset(parent, s, sizeof(int)*n);
bfs(s, t, parent);
for (int i=0; i<links; i++) {
if (visited[e[i].from-1] && !visited[e[i].to-1] && !rGraph[e[i].from-1][e[i].to-1])
cout << e[i].from << " " << e[i].to << endl;
else if (visited[e[i].to-1] && !visited[e[i].from-1] && !rGraph[e[i].to-1][e[i].from-1])
cout << e[i].from << " " << e[i].to << endl;
}
cout << endl;
}
}