-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathedmonds_karp.cpp
178 lines (144 loc) · 3.86 KB
/
edmonds_karp.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
169
170
171
172
173
174
175
176
177
178
#include <bits/stdc++.h>
using namespace std;
const int N = 105; // Max number of nodes
const int M = 105; // Max number of edges
//
// Graph related variables.
//
int n, m; // The number of nodes and number of edges
int edgeId; // The next edge id to be inserted.
int head[N]; // head[u] : the id of the last edge added from node "u".
int nxt[M]; // nxt[e] : the next edge id pointed from the same node as "e".
int to[M]; // to[e] : the id of the node pointed by edge "e".
int capacity[M]; // capacity[e] : the maximum capacity of edge "e".
//
// Max flow related variables.
//
int src, snk; // the id of source and sink nodes.
int dist[N]; // dist[u] : the shortest distance between the source and node "u".
int from[N]; // from[u] : the id of the edge that leads to node "u" in the path from source to sink.
int flow[M]; // flow[u] : the current flow of edge "e".
/**
* Initializes the graph.
* Must be called before each test case.
*/
void init() {
edgeId = 0;
memset(head, -1, sizeof(head));
}
/**
* Adds a new directed edge in the graph from node "f" to node "t"
* with maximum capacity "c".
*
* @param f the source node.
* @param t the target node.
* @param c the capacity of the edge.
*/
void addEdge(int f, int t, int c) {
int e = edgeId++;
to[e] = t;
capacity[e] = c;
flow[e] = 0;
nxt[e] = head[f];
head[f] = e;
}
/**
* Adds a new augmented edge in the graph between node "f" and node "t"
* with maximum capacity "w".
*
* @param f the first node.
* @param t the second node.
* @param c the capacity of the edge.
*/
void addAugEdge(int f, int t, int c) {
addEdge(f, t, c);
addEdge(t, f, 0);
}
/**
* Finds a path from the source to the sink while respecting
* the constraints on the capacities of the edges.
*
* Do not call this function directly.
*
* Complexity: O(V+E)
*
* @return {@code true} if a path is found; {@code false} otherwise.
*/
bool findPath() {
queue<int> q;
q.push(src);
memset(dist, -1, sizeof(dist));
dist[src] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int e = head[u]; ~e; e = nxt[e]) {
int v = to[e];
int c = capacity[e];
int f = flow[e];
if (f >= c) {
continue;
}
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
from[v] = e;
q.push(v);
}
if (v == snk) {
return true;
}
}
}
return false;
}
/**
* Augments the previously found path to the flow graph.
*
* Do not call this function directly.
*
* @return the maximum flow of the previously found path.
*/
int augmentPath() {
int f = INT_MAX;
// Calculate maximum flow of the found path
for (int u = snk, e, r; u != src; u = to[r]) {
e = from[u]; // x ---e--> u
r = e ^ 1; // x <--r--- u
f = min(f, capacity[e] - flow[e]);
}
// Augment path
for (int u = snk, e, r; u != src; u = to[r]) {
e = from[u]; // x ---e--> u
r = e ^ 1; // x <--r--- u
flow[e] += f;
flow[r] -= f; // Reversed edge for flow cancelation
}
return f;
}
/**
* Calculates the maximum flow of the graph.
*
* Complexity: O(min(V.E^2, (V+E).MaxFlow))
*
* @return the value of the maximum flow.
*/
int maxFlow() {
int f = 0;
while (findPath()) {
f += augmentPath();
}
return f;
}
/**
* Reads and constructs the graph.
*/
void read() {
cin >> n >> m;
init();
src = 1, snk = n;
while (m--) {
int u, v, c;
scanf("%d %d %d", &u, &v, &c);
addAugEdge(u, v, c);
}
}