1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- // 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:
- // - oriented 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).
- 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;
- }
- };
|