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)的残存容量 )。
下面是一小组测试数据以及程序,之后,将给出程序运行的图解。在结尾,简单地分析一下算法的正确性以及时间复杂度,并附带图中所使用的样例,以方便您进行测试。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/c189af04033eb976510621d68f9be295)
核心代码的导引:
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];
}
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/c189af04033eb976510621d68f9be295)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/4a2d96bde35c69ea71ab76d6c49ace71)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/a0fa3a9ff51292094e45cace1e24bfce)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/99c13f55aca4c7bf7c0162e1c44c5152)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/741b2adce17c7cad8506410599ad2f50)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/19f72377f3399b4d132b62eea91c9310)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/34ca1c6886f5d10533db789edf88b59f)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/273c09fbdaae95fad7f2411e7976b529)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/d0119655040ef68ff48b1933e0b3bd24)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/af317c29e5c6c1d7933bfa82aae8461c)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/cdca99f47404529c2f1ca272c534c01f)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/f18eadf68cc26204cf73ffa58771188b)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/1af2a5b896de2a5d15a204233997055a)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/1fe79482c507bf8f33def43c2725b1bb)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/5ba5c88abbdeb69c87c5879b05a24b05)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/65b6d376113b2a8836165e9a36b1db24)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/1890d209a576e3c41a58b62d9fcd9a75)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/24/59f6e171f658650031a547571b698007)
![](https://img-blog<br/>4000<br/>.csdn.net/20140707214423265)
算法的正确性不难说明,程序结束时,残存网络中已经不含增广路,此时的流量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
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
相关文章推荐
- 最大流的Ford-Fulkerson方法初步
- 算法——最大流:Ford-Fulkerson方法
- 最大流:Ford-Fulkerson方法DFS实现
- 求最大流Ford-Fulkerson方法(Edmonds-Karp算法)
- 最大流之Ford-Fulkerson方法详解及实现
- 最大流之Ford-Fulkerson方法详解及实现
- 网络最大流之一般增广路方法------Ford-Fulkerson
- 最大流的Ford-Fulkerson方法初步
- 最大流算法--Ford-Fulkerson方法及其多种实现
- poj 1273 最大流 ford-fulkerson
- 图的匹配问题与最大流问题(二)——最大流问题Ford-Fulkerson方法
- 网络最大流算法之 Ford_Fulkerson方法,EK算法 c++模板
- HDU 3549 Flow Problem【Ford-Fulkerson+DFS 最大流】
- [转] 网络流算法--Ford-Fulkerson方法及其多种实现
- 一般增广路方法求网络最大流(Ford-Fulkerson算法)
- [图论]最大流介绍 Ford-Fulkerson算法 邻接表实现
- 《网络流学习笔记02--Edmonds-Karp,Ford-Fulkerson,Dinic三种算法实现最大流》
- Ford-Fulkerson求解最大流
- Ford-Fulkerson 最大流算法
- 图的匹配问题与最大流问题(三)——最大流问题Ford-Fulkerson方法Java实现