您的位置:首页 > 其它

求最大流Ford-Fulkerson方法(Edmonds-Karp算法)

2017-04-07 12:05 260 查看

基本思路:

算法导论第26章

使用反平行边来模拟残存网络

在残存网络中用广搜来寻找增广路径(用pre数组记录前驱结点)。

如找不到增广路径,已达到最大流,结束

如找到增广路径,最大流的增值为增广路径上的权值的最小值。

更新残存网络(从汇点通过前驱数组沿增广路径向前更新)。

更新最大流。

转步骤2。

example:

如下图找出从节点16的最大流。



输入:

6 9

1 2 16

2 4 12

4 6 20

5 6 4

3 5 14

1 3 13

3 2 4

4 3 9

5 4 7

1 6

输出:

23

#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define MAXN 5000
using namespace std;
int n, S, T;                 //节点数,源点,汇点
vector<vector<int>> capacity;//残存网络的邻接矩阵
queue<int> qu;               //广搜队列
int pre[MAXN], flow[MAXN];   //前驱数组;增广路径中的节点流
int find_augmenting_path(int s, int t) {
int index;
size_t i;
memset(pre, -1, n * sizeof(int));
while (!qu.empty()) qu.pop();
flow[s] = INF; //源点的流为INF
qu.push(s);
while (!qu.empty()) {
index = qu.front();
qu.pop();
if (index == t)break; //找到了一条增广路径
for (i = 0; i < n; ++i)
if (i != s && capacity[index][i] > 0 && pre[i] == -1) {//每个节点只遍历一次
pre[i] = index;
flow[i] = min(capacity[index][i], flow[index]);
qu.push(i);
}
}
if (pre[t] == -1)return 0;
return flow[t];

}
int maxflow(int s, int t) {
int sumflow = 0, increaseflow, v, prenode;
while (increaseflow = find_augmenting_path(s, t)){
v = t;
while (v != s) { //从汇点通过前驱数组向源点更新残存网络
prenode = pre[v];
capacity[prenode][v] -= increaseflow;
capacity[v][prenode] += increaseflow;
v = prenode;
}
sumflow += increaseflow;
}
return sumflow;
}
int main() {
size_t i, m;
int s, t, c;
while (cin >> n >> m ) {
capacity.assign(n, vector<int>(n, 0));
for (i = 0; i < m; ++i) {
cin >> s >> t >> c;
s--, t--;
capacity[s][t] = c;
}
cin >> S >> T;
cout << maxflow(S - 1, T - 1) << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息