-
Notifications
You must be signed in to change notification settings - Fork 1
/
Max Flow Dinic.cpp
134 lines (113 loc) · 3.42 KB
/
Max Flow Dinic.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
// From Stanford ACM Notebook
// Adjacency list implementation of Dinic's blocking flow algorithm.
// This is very fast in practice, and only loses to push-relabel flow.
//
// Running time:
// O(|V|^2 |E|)
//
// INPUT:
// - graph, constructed using AddEdge()
// - source
// - sink
//
// OUTPUT:
// - maximum flow value
// - To obtain the actual flow values, look at all edges with
// capacity > 0 (zero capacity edges are residual edges).
#include <stdio.h>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <math.h>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <iostream>
#include <algorithm>
#include <deque>
#include <assert.h>
using namespace std;
#define clr(a) (a.clear())
#define MP(a,b) make_pair(a,b)
#define sz(x) (int)x.size()
#define mem(a,b) memset(a, b, sizeof(a))
#define Unique(store) store.resize(unique(store.begin(),store.end())-store.begin())
#define pb push_back
const int INF = 2000000000;
struct Edge {
int from, to, cap, flow, index;
Edge(int from, int to, int cap, int flow, int index) :
from(from), to(to), cap(cap), flow(flow), index(index) {}
};
struct Dinic {
int N;
vector<vector<Edge> > G;
vector<Edge *> dad;
vector<int> Q;
Dinic(int N) : N(N), G(N), dad(N), Q(N) {}
void AddEdge(int from, int to, int cap) {
G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
if (from == to) G[from].back().index++;
G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
}
long long BlockingFlow(int s, int t) {
fill(dad.begin(), dad.end(), (Edge *) NULL);
dad[s] = &G[0][0] - 1;
int head = 0, tail = 0;
Q[tail++] = s;
while (head < tail) {
int x = Q[head++];
for (int i = 0; i < G[x].size(); i++) {
Edge &e = G[x][i];
if (!dad[e.to] && e.cap - e.flow > 0) {
dad[e.to] = &G[x][i];
Q[tail++] = e.to;
}
}
}
if (!dad[t]) return 0;
long long totflow = 0;
for (int i = 0; i < G[t].size(); i++) {
Edge *start = &G[G[t][i].to][G[t][i].index];
int amt = INF;
for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
if (!e) {
amt = 0;
break;
}
amt = min(amt, e->cap - e->flow);
}
if (amt == 0) continue;
for (Edge *e = start; amt && e != dad[s]; e = dad[e->from]) {
e->flow += amt;
G[e->to][e->index].flow -= amt;
}
totflow += amt;
}
return totflow;
}
long long GetMaxFlow(int s, int t) {
long long totflow = 0;
while (long long flow = BlockingFlow(s, t))
totflow += flow;
return totflow;
}
};
int main() {
int node, edge, source, sink;
while(scanf("%d", &node) == 1 && node) {
scanf("%d %d %d", &source, &sink, &edge);
Dinic din(node);
for(int i = 0; i < edge; i++) {
int from, to, cap;
scanf("%d %d %d", &from, &to, &cap);
--from, --to;
din.AddEdge(from, to, cap);
din.AddEdge(to, from, cap);
}
printf("Maximum Flow from source to sink is : %lld\n", din.GetMaxFlow(--source, --sink));
}
return 0;
}