这些算法都是基于Ford-Fulkerson 方法,
这个方法基本上是这样的一个循环:
Cap = 0;
while find Augmenting Path != NIL
Cap += decrease capacity of the Augmenting path
return Cap;
就是循环的寻找Augmenting Path(增广路径), 然后再在图上的边的Capacity(容量)上减去这个值, 这样一直找, 知道找不到增广路径位置。
首先是一个基于BFS(广度有限搜索)的算法, 名字叫做: Edwinds-Karp alg:
下面是一个C++实现:
#include <vector>
#include <unordered_set>
#include <queue>
#include <cmath>
#include <climits>
#include <cstring>
using namespace std;
vector< vector<int> > matrix;
vector< vector<int> > capacity;
int bfs(int source, int size, int sink) {
queue<int> q;
q.push(source);
int from[size];
bool visited[size];
memset(from, -1, sizeof(from));
memset(visited, false, sizeof(visited));
visited[source] = true;
// use bfs find the route to the sink.
while(!q.empty()) {
bool found_sink = false;
int where = q.front();
q.pop();
// for each vertex next adjancent to where.
for (auto next = matrix[where].begin(); next != matrix[where].end(); next++) {
int val = *next;
if (visited[val] == true)
continue;
if (capacity[where][val] > 0) {
q.push(val);
visited[val] = true;
from[val] = where;
if (val == sink) {
found_sink = true;
break;
}
}
}
if (found_sink)
break;
}
// then compute the path capacity.
// Find the critical path from the sink back to source.
// find the minimal path capacity of the path.
int where = sink, prev, path_cap = INT_MAX;
while (from[where] > -1) {
prev = from[where];
path_cap = min(path_cap, capacity[prev][where]);
where = prev;
}
// then update the residual network, if no path is found the while loop will not be enter.
// Then - augment.
where = sink;
while (from[where] > -1) {
prev = from[where];
capacity[prev][where] -= path_cap;
capacity[where][prev] += path_cap;
where = prev;
}
// if no path is found, path_cap is infinity.
// and return the augmenting capacity.
if (path_cap == INT_MAX)
return 0;
else
return path_cap;
}
int max_flow()
{
int result = 0, path_cap ;
while (true) {
path_cap = bfs(1, 8, 7);
if (path_cap == 0)
break;
else
result += path_cap;
}
return result;
}
这个实现的是基于BFS的。
BFS 里面的循环基本就是一个标准的BFS遍历方法, 检测条件的时候增加了一个路径的Capacity(容量)必须大于0, 这样就不会找到已经满了路径了。顺着source一直走到sink以后, 记录下路径。
然后通过sink反着找到Capacity最小的一条边, 记录这个值。
最后在路径上对于正方向, 减去这个指, 对于反方向, 增加这个值。并且返回这个数值。
这个实现的算法复杂度是O(VE²), 因为BFS的负责读是O(E), 而其他每一次找增广路径的计算的复杂度是O(V)。