forked from matthewsamuel95/ACM-ICPC-Algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GoldbergTarjan.cc
89 lines (73 loc) · 1.82 KB
/
GoldbergTarjan.cc
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
#include <bits/stdc++.h>
using namespace std;
const int N = 100 , INF = (int)2e9; // Max nodes and flow
int nodes, // number of nodes
F[N+2][N+2], // flow
C[N+2][N+2], // edge cap
xf[N+2], // excess flow
ht[N+2], // height
nxt[N+2]; // adjacent node pointer
inline void pushExcess(int u, int v) {
int df = min(xf[u] , C[u][v] - F[u][v]);
F[u][v] += df , F[v][u] -= df;
xf[u] -= df, xf[v] += df;
}
inline void relabelNode(int u){
int min_ht = 2*nodes;
for(int v = 0; v < nodes; v++)
if( C[u][v] > F[u][v] ) min_ht = min(min_ht,ht[v]);
ht[u] = min_ht+1;
}
void discharge(int u) {
while( xf[u] > 0 ) {
int v = nxt[u];
if( v < nodes ) { // push excess flow downhill
if( C[u][v] > F[u][v] and ht[u] > ht[v] ) pushExcess(u,v);
else ++nxt[u];
} else { // relabel and rewind
relabelNode(u); nxt[u] = 0;
}
}
}
int GoldbergTarjan(int src=0, int sink=nodes-1) {
fill(xf,xf+nodes,0);
fill(ht,ht+nodes,0);
fill(nxt,nxt+nodes,0);
int list[nodes-2];
for(int i=0,j=0;i<nodes;i++) {
if( i==src or i==sink ) continue;
list[j++] = i;
}
ht[src] = nodes; xf[src] = INF;
for(int i=0;i<nodes;i++)
if(i != src) pushExcess(src,i);
int index = 0;
while( index < nodes-2 ) {
int u = list[index];
int prev_ht = ht[u];
discharge(u);
if( ht[u] > prev_ht ) { // move to front
for(int j=index-1;index>0;index--,j--)
list[index] = list[j];
list[0] = u;
} else {
index++;
}
}
int maxFlow = 0;
for(int v = 0; v < nodes; v++)
maxFlow += F[src][v];
return maxFlow;
}
int main() {
cin >> nodes;
for(int i=0; i<nodes; i++) {
for(int j=0; j<nodes; j++) {
cin >> C[i][j];
F[i][j] = 0;
}
}
int max_flow = GoldbergTarjan(0, nodes-1);
cout << max_flow << endl;
return 0;
}