网络最大流求解 增广路算法
来源:互联网 发布:nginx php 跨域 编辑:程序博客网 时间:2024/04/27 22:25
增广路算法:
根据增广路地理,为了得到最大流,可以从任何一个可行流开始,沿着增广路对网络流进行增广,直到网络中不存在增广路为止,这样的算法称为增广路算法。
增广路算法流程如下。
(1)取一个可行流f作为初始流(如果没有给定可行流,则取零流作为初始流)。
(2)寻找关于f的增广路P,如果找到,则沿着这条增广路P将f改进成一个更大的流。
(3)重复 第(2)步直到找不到增广路为止。
增广路算法的关键是寻找增广路和改进网络流。
主要有三种增广路算法。(1)Ford_Fulkerson算法。(2)最短增广路算法。(3)Dinic算法(连续增广路算法)。后两种算法效率更高。
Ford_Fulkerson算法:
#include <algorithm>#include <iostream>#include <sstream>#include <cstring>#include <cstdio>#include <vector>#include <cctype>#include <cmath>#include <stack>#include <queue>#include <list>#include <map>#include <set>using namespace std;typedef long long ll;typedef unsigned long long ull;const int maxn = 1000;const int inf = 10000000;struct arc{int c,f;//容量、流量 };int n,m;arc edge[maxn][maxn];int flag[maxn];//顶点状态 -1为标号 0已标号未检查 1已标号已检查 int prev[maxn];//标号的第1个分量 int al[maxn];//标号的第2个分量 void printFlow(){int maxFlow = 0;for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){if(i == 0 && edge[i][j].f != inf) maxFlow += edge[i][j].f;if(edge[i][j].f != inf) printf("%d->%d:%d\n",i,j,edge[i][j].f);}}printf("maxFlow:%d\n",maxFlow);}void input(){int u,v,c,f;scanf("%d%d",&n,&m);for(int i = 0; i < n; i++){for(int j = 0; j < n; j++)edge[i][j].c = edge[i][j].f = inf;}for(int i = 0; i < m; i++){scanf("%d%d%d%d",&u,&v,&c,&f);edge[u][v].c = c;edge[u][v].f = f;}}void ford_fulkerson(){while(1)//直至标号不存在 {queue<int> q;memset(flag,-1,sizeof(flag));memset(prev,0,sizeof(prev));memset(al,0,sizeof(al));flag[0] = 0; prev[0] = 0; al[0] = inf;q.push(0);//队列非空并且汇点未标号 while(!q.empty() && flag[n-1] == -1) {int v = q.front(); q.pop();for(int i = 0; i < n; i++){if(flag[i] == -1)//该顶点未标号 {//正向且流量未满if(edge[v][i].c != inf && edge[v][i].f < edge[v][i].c){//标号 flag[i] = 0; prev[i] = v;al[i] = min(al[v],edge[v][i].c - edge[v][i].f);q.push(i);}//反向且有流量else if(edge[i][v].c != inf && edge[i][v].f > 0) {flag[i] = 0; prev[i] = -v;al[i] = min(al[v],edge[i][v].f);q.push(i);}}flag[v] = 1;//该顶点已检查 }}//end of while//汇点未标号或者调整量为0 if(flag[n-1] == -1 || al[n-1] == 0) break;int p1 = n-1,p2 = abs(prev[p1]);int a = al[n-1];while(1){if(edge[p2][p1].f != inf) edge[p2][p1].f += a;else edge[p1][p2].f -= a;if(p2 == 0) break;p1 = p2;p2 = abs(prev[p1]);};}//end of while(1)//最大流 printFlow();}//end of fordint main(){input();//初始流 printFlow();ford_fulkerson(); return 0;}/* input: 6 100 1 8 20 2 4 31 3 2 21 4 2 22 1 4 22 3 1 12 4 4 03 4 6 03 5 9 34 5 7 2output:0->1:20->2:31->3:21->4:22->1:22->3:12->4:03->4:03->5:34->5:2maxFlow:50->1:40->2:41->3:21->4:22->1:02->3:12->4:33->4:03->5:34->5:5maxFlow:8*/
下面两个是两个改版Ford_Fulkerson算法,分别用dfs和bfs来寻找增广路:
bfs:
#include <iostream>#include <algorithm>#include <cstring>#include <queue>using namespace std;const int maxn = 1005;const int inf = 100000;struct Arc{ int c,f;//容量、流量 };int n,m; Arc edge[maxn][maxn];int vis[maxn];int a[maxn];int p[maxn];void input(){ int u,v,c,f; scanf("%d%d",&n,&m); for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ edge[i][j].c = edge[i][j].f = inf; } } for(int i = 0; i < m; i++){ scanf("%d%d%d%d",&u,&v,&c,&f); edge[u][v].c = c; edge[u][v].f = f; } }//寻找增广路 int bfs(){ queue<int> q; memset(vis,0,sizeof(vis)); q.push(0); vis[0] = 1; a[0] = inf; //找到一条增广路 while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < n; i++){ if(!vis[i]){ //正向且未满 if(edge[u][i].c != inf && edge[u][i].f < edge[u][i].c){ vis[i] = 1; p[i] = u; a[i] = min(a[u],edge[u][i].c-edge[u][i].f); q.push(i); } //反向且有流量 else if(edge[i][u].c != inf && edge[i][u].f > 0){ vis[i] = 1; p[i] = -u; a[i] = min(a[u],edge[i][u].f); q.push(i); } } } vis[u] = 1; if(vis[n-1]) break; } if(!vis[n-1]) return 0; //增广 int t = n-1; int alpha = a[n-1]; while(t != 0){ if(p[t] >= 0){//正向 edge[p[t]][t].f += alpha; } else{//反向 edge[t][-p[t]].f -= alpha; } t = abs(p[t]); } return a[n-1];}void printFlow() { int maxFlow = 0; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if(i == 0 && edge[i][j].f != inf) maxFlow += edge[i][j].f; if(edge[i][j].f != inf) printf("%d->%d:%d\n",i,j,edge[i][j].f); } } printf("maxFlow:%d\n",maxFlow); } int main(){ input(); printFlow(); while(bfs()); printFlow(); return 0;}/* input: 6 10 0 1 8 2 0 2 4 3 1 3 2 2 1 4 2 2 2 1 4 2 2 3 1 1 2 4 4 0 3 4 6 0 3 5 9 3 4 5 7 2 output: 0->1:2 0->2:3 1->3:2 1->4:2 2->1:2 2->3:1 2->4:0 3->4:0 3->5:3 4->5:2 maxFlow:5 0->1:4 0->2:4 1->3:2 1->4:2 2->1:0 2->3:1 2->4:3 3->4:0 3->5:3 4->5:5 maxFlow:8 */
dfs:
#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <queue>using namespace std;const int maxn = 1005;const int inf = 100000;struct Arc{ int c,f;//容量、流量 };int n,m; Arc edge[maxn][maxn];int vis[maxn];void input(){ int u,v,c,f; scanf("%d%d",&n,&m); for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ edge[i][j].c = edge[i][j].f = inf; } } for(int i = 0; i < m; i++){ scanf("%d%d%d%d",&u,&v,&c,&f); edge[u][v].c = c; edge[u][v].f = f; } }int dfs(int u, int alpha){ if(u == n-1) return alpha; if(vis[u]) return 0; vis[u] = 1; for(int i = 0; i < n; i++){ if(!vis[i]){ int flow; //正向且未满 if(edge[u][i].c != inf && edge[u][i].f < edge[u][i].c){ flow = dfs(i,min(alpha,edge[u][i].c-edge[u][i].f)); edge[u][i].f += flow; if(flow != 0) return flow; } //反向且有流量 else if(edge[i][u].c != inf && edge[i][u].f > 0){ flow = dfs(i,min(alpha,edge[i][u].f)); edge[i][u].f -= flow; if(flow != 0) return flow; } } } return 0;}void printFlow() { int maxFlow = 0; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if(i == 0 && edge[i][j].f != inf) maxFlow += edge[i][j].f; if(edge[i][j].f != inf) printf("%d->%d:%d\n",i,j,edge[i][j].f); } } printf("maxFlow:%d\n",maxFlow); } int main(){ input(); printFlow(); while(dfs(0,inf)){ //printFlow(); memset(vis,0,sizeof(vis)); } printFlow(); return 0;}/* input: 6 10 0 1 8 2 0 2 4 3 1 3 2 2 1 4 2 2 2 1 4 2 2 3 1 1 2 4 4 0 3 4 6 0 3 5 9 3 4 5 7 2 output: 0->1:2 0->2:3 1->3:2 1->4:2 2->1:2 2->3:1 2->4:0 3->4:0 3->5:3 4->5:2 maxFlow:5 0->1:4 0->2:4 1->3:2 1->4:2 2->1:0 2->3:1 2->4:3 3->4:0 3->5:3 4->5:5 maxFlow:8 */
0 0
- 网络最大流求解 增广路算法
- 增广路算法 Ford-Fulkerson算法 网络最大流问题
- 最大流增广路算法
- 网络流初步 增广路算法求最大流 hdoj3549
- 网络流初步之最大流(增广路算法)
- 网络流——最大流增广路算法
- MaxFlow(最大流增广路算法)
- 最大流 - Edmonds-Karp 增广路算法
- PIGS(最大流_增广路算法)
- 最大流的增广路算法比较
- poj 1459 最大流增广路算法
- [最大流]增广路算法Edmonds-Karp
- 网络流之最大流的增广路径算法
- 网络流DINIC增广路算法介绍
- 基于增广路的网络流算法
- 网络流之增广路算法
- 最大流增广路
- 网络最大流中一般增广路算法(标号法)
- phpcms 更换域名步骤
- quick-cocos2dx 半成品 UILoadingBar
- php开发之加密
- Oracle实例创建
- 对象创建过程,初始化顺序
- 网络最大流求解 增广路算法
- 蚂蚁感冒
- 鲍鹏山:我们培养了很多高学历的野蛮人 导读: 德国哲学家尼采写过一篇文章叫《我为什么这么聪明》。他的结论就一句话:我之所以这么聪明,是因为我从来不在不必要的事情上浪费精力。生活中有太多这样无用
- 深圳小产权房公明罗群围花园
- Web Service
- Windows下Python的强力助手——Pypi
- OpenGL笔记之矩阵变换(Matrix Transformation)
- extern c , c++ 调用c
- SuperMap IObjects C++组件学习笔记(一) - Hello iObjects C++