最大流的问题就不重复了,思路如下:
每次找到一条从s到t的路径, 其容量为所经历的所有边上容量最小的一个;
将这个路径的容量加入图的总容量;
沿着刚才那条路径走,沿两个方向更新边
找路径可以用bfs, 每次bfs 为了保证不重复经过同一个点,可以用visit数组纪录这个点是否被访问过;
再用一个一维数组纪录路径就可以了
这种方法里 edmonds carp的复杂度是O(NE)
为了更好的说明edmonds carp算法,练了一道poj 1273题,
代码如下
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 205;
long long flw[maxn][maxn];
int n, m;
long long edmondscarp(){
long long sumrt = 0;
while(true){
int visit[maxn], recroute[maxn];
memset(visit, 0, sizeof(visit));
memset(recroute, -1, sizeof(recroute));
visit[1] = 1;
queue<int> aqueue;
aqueue.push(1);
long long minflw = 0x7fffffff;
bool findrt = false;
while(!aqueue.empty()){
int p = aqueue.front();
aqueue.pop();
for(int j = 1; j <= n; ++j){
if((!visit[j]) && flw[p][j] > 0){
minflw = min(minflw, flw[p][j]);
recroute[j] = p;
if(j == n){
findrt = true;
break;
}
aqueue.push(j);
visit[j] = true;
}
}
if(findrt){
break;
}
}
if(!findrt){
break;
}
sumrt += minflw;
int curp = n;
for(curp = n; curp != 1; curp = recroute[curp]){
flw[recroute[curp]][curp] -= minflw;
flw[curp][recroute[curp]] += minflw;
}
}
return sumrt;
}
int main(){
while(scanf("%d%d",&m, &n)!=EOF){
memset(flw, 0, sizeof(flw));
long long s, e, c;
for(int i = 1; i <= m; ++i){
scanf("%lld%lld%lld", &s, &e, &c);
flw[s][e] += c;
}
printf("%lld\n",edmondscarp());
}
return 0;
}