Edmond Karp Max Flow (Network Flow)ΒΆ
Note
Tested On: UVA820, UVA259
#include <vector>
#include <queue>
#include <limits>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAX 110
vector<int> G[MAX];
int W[MAX][MAX]; // Stores the edges weights -- memset to 0
int parent[MAX]; // Stores the nodes' parents -- memset to -1
int get_min_edge(int node, int min_edge, int source_node)
{
if (node == source_node)
return min_edge;
// If the node has a parent
else if (parent[node] != -1)
{
auto parent_node = parent[node];
auto flow = get_min_edge(parent_node, min(min_edge, W[parent_node][node]), source_node);
W[parent_node][node] -= flow; // Descreases flow
W[node][parent_node] += flow; // Increases flow
return flow;
}
return 0;
}
bool visited[MAX]; // memset to false
int max_flow_edmonds_karp(int source_node, int target_node)
{
/*
Finds the max flow of a directed weighted graph
!! All edges must have a backward edge, they will have different weights
Complexity: O(V * E^2)
*/
int max_flow = 0, flow;
while (true)
{
flow = 0;
// Using BFS to build the parent array
queue<int> to_visit;
memset(visited, false, sizeof visited);
memset(parent, -1, sizeof parent);
visited[source_node] = true;
to_visit.push(source_node);
while(!to_visit.empty())
{
auto node = to_visit.front();
to_visit.pop();
if (node == target_node) break;
for(auto adjacent: G[node])
{
// Excludes the edges without flow and already visited
if (W[node][adjacent] > 0 and not visited[adjacent])
{
visited[adjacent] = true;
to_visit.push(adjacent);
parent[adjacent] = node;
}
}
}
// Get the minimum edge value from source to target
flow = get_min_edge(target_node, numeric_limits<int>::max(), source_node);
if (flow == 0) break; // No more flow in the graph
max_flow += flow;
}
return max_flow;
}