您的位置:首页 > 其它

Ford-Fulkerson方法求最大流

2014-07-07 21:37 204 查看
本文试图用通俗的说法描述这个最大流算法,有关名称的准确定义请您参考其他资料

Ford-Fulkerson方法(G,s,t )

    初始化最大流f等于0

    while 在残存网络里存在一条增广路径

        根据 该增广路径 更新最大流f 以及残存网络 

return f 

    边的残存容量:原来的图中的每条边都有一个容量,随着算法的实施,在一些时刻有些边允许的容量在减小,而有些时候一些边的容量在增加,换句话说,在求最大流的过程中,图中的边的容量是变化的,于是用残存容量来刻画一条边在当前状态还能通过的流量。残存容量大于零的边构成残存网络。残存网络中从源点s到汇点t的一条简单路径称为增广路径

    每次寻求一条增广路企图增加从源点到汇点的流量。由于采用BFS搜索,所以能够保证每次找到的增广路是最短的。每次寻求增广路的过程中,使用r [ u ] 来存储表示从源点到达 u 点的最大可能的流量,假设我们的搜索路径中有这样的一条边
(u ,v)。那么,r [u ]= min( r[u] , (u,v)的残存容量 )。

下面是一小组测试数据以及程序,之后,将给出程序运行的图解。在结尾,简单地分析一下算法的正确性以及时间复杂度,并附带图中所使用的样例,以方便您进行测试。



核心代码的导引:

while(1){
设置从源点到图中每一点的最大流量为零
源点入队Q,设置源点到源点的最大流量为无穷大
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int v=1;v<=n;v++){
if(v还没被访问过并且u到v的残存容量大于零){
r[v]=min(r[u],u到v的残存容量);
Q.push(v);pa[v]=u;
}
}
}
if(源点到汇点的流量为零)break;
for(int u=t;u!=s;u=pa[u]){
更新正向残存容量;
更新反向残存容量;
}
f+=r[t];
}

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
#define maxn 100
#define INF 100000000
using namespace std;
int cap[maxn+10][maxn+10];//容量
int flow[maxn+10][maxn+10];//流量
int r[maxn+10];//最小残存容量
int pa[maxn+10];//记录增广路
int s,t,n,m;
queue<int> Q;
int BFS(int s,int t){
int f=0;
memset(flow,0,sizeof(flow));
while(1){
memset(r,0,sizeof(r));memset(pa,0,sizeof(pa));
Q.push(s);r[s]=INF;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int v=1;v<=n;v++){
if(!r[v]&&cap[u][v]>flow[u][v]){
r[v]=min(r[u],cap[u][v]-flow[u][v]);
Q.push(v);pa[v]=u;
}
}
}
if(r[t]==0)break;
for(int u=t;u!=s;u=pa[u]){
flow[pa[u]][u]+=r[t];
flow[u][pa[u]]-=r[t];
}
f+=r[t];
}
return f;
}
int main(){
freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
memset(cap,0,sizeof(cap));
for(int i=0;i<m;i++){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
cap[u][v]=c;
}
scanf("%d%d",&s,&t);
printf("%d\n",BFS(s,t));
return 0;
}








































    算法的正确性不难说明,程序结束时,残存网络中已经不含增广路,此时的流量f即是G的一个最大流。通过反正,假设f是G的最大流,同时残存网络中还有一条增广路p,我们就可以用p来更新最大流得到更大的最大流。由于每次寻路都会将流量至少增加1个单位,那么while 循环至多执行f次,这里f是最大流量。使用广度优先搜索算法寻找最短路径,时间是O(E)。所以总的时间复杂度是O(f*E)。

6 9

1 2 16

1 3 13

2 3 10

2 4 12

3 2 4

3 5 14

4 3 9 

4 6 20

5 6 4

1 6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: