Maximum Flow
Authors: Benjamin Qi, Mihnea Brebenel, Ahmet Ala
Introduces maximum flow as well as flow with lower bounds.
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
CSES | Easy | Show TagsMax Flow |
Solution
Explanation
The Edmonds-Karp algorithm uses a greedy approach to solve the maximum flow problem.
The download speed (the flow) can be improved as long as we can find a non-negative capacity augmenting path from the source (the server) to the sink (Kotivalo's computer). We use BFS to find this path.
Then, we update the weights of the edges along this augmenting path. Each edge , loses weight equivalent to its capacity in the augmenting path, while each reverse edge , gains this weight.
It can be proven that the total number of flow augmentations(BFS calls) is and that each BFS call requires time.
Implementation
Time complexity:
C++
#include <bits/stdc++.h>using namespace std;long long max_flow(vector<vector<int>> adj, vector<vector<long long>> capacity,int source, int sink) {int n = adj.size();vector<int> parent(n, -1);// Find a way from the source to sink on a path with non-negative capacitiesauto reachable = [&]() -> bool {queue<int> q;
Push-Relabel Algorithm
The Push-Relabel Algorithm is an alternative solution to finding the maximum flow.
To find the maximum flow, we'll handle a preflow. The only difference between this and a normal flow is that the incoming flow can exceed the outgoing flow.
Let's define the excess flow of node u as , where is the incoming flow and is the outgoing flow.
The algorithm starts with an initial preflow where the source has an excess flow. At every stage, it picks a node with the excess flow and pushes the excess to its neighbors, if the capacity supports it. To push excess flow from node to node , we define , where is the maximum supported flow by the edge . The process stops when no more excess nodes exist in the flow network.
Another important feature of the algorithm is the labeling function , also known as the height function, which assigns each node an integer. One labeling in valid if satisfies the following conditions: , , and . If there is an edge from node to node with positive capacity, i.e. it supports more flow. The height function tells us where to send the excess flow, and where it's needed. It's like water, it can only flow from top to bottom.
To summarize: Start with a valid preflow and a valid labeling. In each step, for every excess node, try to push the excess flow to the node's neighbors. After each step check if the flow and the labeling are still valid. If they are and there are no more paths between the and the , it means the maximum flow has been found.
The difference between the Edmonds-Karp (or Ford-Fulkerson) and the Push-Relabel algorithm is that the former keeps a valid flow all the time and improves it while there are augmenting paths, while in the Push-Relabel there doesn't exist an augmenting path at any time, and it improves the preflow until it reaches the maximum flow.
Time complexity:
C++
#include <bits/stdc++.h>#define ll long longusing namespace std;const int MAXN = 5000;const ll INF = 1e15;int n, m, source, sink;ll capacity[MAXN + 1][MAXN + 1];
Resources
Flows
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
CSES | Easy | Show TagsMax Flow |
Bipartite Matching
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
CSES | Easy | Show TagsMax Flow |
It's recommended that you solve the first problem - Download Speed - in the section before trying this one.
Solution 1
A bipartite graph doesn't seem like to have anything in common with a flow network, but we can shift our point of view just by adding the source connected to the nodes in set and the sink connected to the nodes in set . And that's all. Now we have a flow network where every capacity is equal to 1.
We transformed our bipartite graph into a network flow so the maximum network flow is equal to the maximum matching. Now, we can apply our favorite max flow algorithm to solve the problem!
Time Complexity:
Solution 2
However, we can do better than this. First let's define some properties of matching algorithms.
Let's say the set contains all the edges that the maximum matching consists of.
We define an alternating path as a path whose edges are in the matching, , and not in the matching, in an alternating fashion. An alternating path stars with an unmatched node and ends once it cannot append another edge while maintaining an alternating sequence.
An augmenting path is built upon the alternating path and unmatched nodes at both ends - the nodes are not included in .
Tha maximum matching can be further improved if and only if an augmenting path is found in , otherwise is the maximum matching. It may seem difficult to understand, but the main idea is as follows:
The maximum matching can be further improved as long as the alternating sequence can be extended.
For a better understanding, you can imagine the shoelaces as an alternating path in a bipartite graph - or the sneakers.
The algorithm described above is called the Hopcroft-Karp algorithm.
Here's an animation of the algorithm if you're still a bit confused:
Time Complexity:
C++
#include <bits/stdc++.h>using namespace std;const int INF = 1e9;int n, m, k;// dist[node] = the position of node in the alternating pathvector<int> match, dist;vector<vector<int>> g;
Dinic's Algorithm
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
SPOJ | Easy | ||||
YS | Easy |
Hopcroft-Karp Bipartite Matching?
Optional: Faster Flow
There exist faster flow algorithms such as Push-Relabel. Also see the following blog post:
However, the standard implementation of Dinic's is (almost) always fast enough on reasonable problems.
Implementation
Resources | ||||
---|---|---|---|---|
Benq |
Breaking Flows
When the constraints are too high ...
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!