//
// main.cpp
// Dinic
//
// Created by Longxiang Lyu on 8/12/16.
// Copyright © 2016 Longxiang Lyu. All rights reserved.
//
// reference:
// https://sites.google.com/site/indy256/algo_cpp/dinic_flow
// the example is from wikipedia page:
// https://en.wikipedia.org/wiki/Dinic%27s_algorithm
// the prove for dinic can be found at:
// http://cseweb.ucsd.edu/classes/sp11/cse202-a/lecture8-final.pdf
// this algorithm is proved to run in O(m*n*n) time
#include
#include
#include
#include
#include
using namespace std;
bool dinic_bfs(vector> &graph, vector &dist, int src, int dest)
{
int V = static_cast(graph.size());
dist.clear();
dist.resize(V, -1);
dist[src] = 0;
queue q;
q.push(src);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v = 0; v != V; ++v)
{
if (dist[v] < 0 && graph[u][v] > 0)
{
dist[v] = dist[u] + 1;
q.push(v);
}
}
}
return dist[dest] >= 0;
}
int dinic_dfs(vector> &graph, vector &dist, int u, int dest, int bottleneck)
{
if (u == dest)
return bottleneck;
int V = static_cast(graph.size());
for (int v = 0; v != V; ++v)
{
if (dist[v] == dist[u] + 1 && graph[u][v] > 0)
{
int _bottleneck = dinic_dfs(graph, dist, v, dest, min(bottleneck, graph[u][v]));
if (_bottleneck > 0)
{
// augment this path
graph[u][v] -= _bottleneck;
graph[v][u] += _bottleneck;
return _bottleneck;
}
}
}
return 0;
}
int dinic(vector> &graph, int src, int dest)
{
int max_flow = 0;
vector dist;
// ensure dest is reachable from src
while (dinic_bfs(graph, dist, src, dest))
{
// find the blocking flow from current residual graph
while(int bottleneck = dinic_dfs(graph, dist, 0, 5, INT_MAX))
max_flow += bottleneck;
}
return max_flow;
}
int main(int argc, const char * argv[]) {
vector> graph = {{0, 10, 10, 0, 0, 0},
{0, 0, 2, 4, 8, 0},
{0, 0, 0, 0, 9, 0},
{0, 0, 0, 0, 0, 10},
{0, 0, 0, 6, 0, 10},
{0, 0, 0, 0, 0, 0}};
cout << "Max Flow: " << dinic(graph, 0, 5) << endl;
return 0;
}