【网络流之最大流算法模板】HDUOJ 3549 Flow Problem
来源:互联网 发布:阿里云余额如何提现 编辑:程序博客网 时间:2024/05/17 02:40
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3549
1、Ford-Fulkerson算法:参见博客详解http://blog.csdn.net/smartxxyx/article/details/9293665/
(1)只利用满足f(e)<c(e)的e或者满足f(e)>0的e对应的反向边rev(e),寻找一条s-t的路径。
(2)如果不存在满足条件的路径,则结束。否则,沿着该路径尽可能地增加流,返回第(1)步。
#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#define INF 0x3f3f3f3ftypedef long long LL;using namespace std;const int maxn=1008;struct edge{ int to,cap,rev;};vector<edge>G[maxn];bool used[maxn];void addedge(int from,int to,int cap){ G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1});}int dfs(int v,int t,int f){ if(v==t) return f; used[v]=true; for(int i=0;i<G[v].size();i++) { edge &e=G[v][i]; if(!used[e.to]&&e.cap>0) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0;}int max_flow(int s,int t){ int flow=0; for(;;) { memset(used,0,sizeof(used)); int f=dfs(s,t,INF); if(f==0) return flow; flow+=f; }}int main(){ int n,m,x,y,z,t,T=0; scanf("%d",&t); while(t--) { scanf("%d%d",&m,&n); memset(used,false,sizeof(used)); for(int i=0;i<=m;i++) G[i].clear(); for(int i=0;i<n;i++) { scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); } int ans=max_flow(1,m); printf("Case %d: %d\n",++T,ans); } return 0;}
2、Dinic算法:Ford-Fulkerson算法是通过深度优先搜索寻找增广路,并沿着它增广。与之相对,Dinic算法总是寻找最短的增广路,并沿着它增广。因为最短增广路的长度在增广的过程中始终不会变短,所以无需每次都通过宽度预先搜索来寻找最短增广路。我们可以先进行一次宽度优先搜索,然后考虑由近距离顶点指向远距离顶点的所组成的分层图,在上面进行深度优先搜索寻找最短增广路。如果在分层图上找不到新的增广路了,则说明最短增广路的长度确实变长了,或不存在增广路了,于是重新通过宽度优先搜索构造新的分层图。
Dinic算法就是Ford-Fulkerson算法的优化。
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<vector>#include<queue>#define INF 0x3f3f3f3ftypedef long long LL;using namespace std;const int maxn=1008;struct edge{ int to,cap,rev;};int can[maxn][maxn];vector<edge>G[maxn];int level[maxn],n,k;//顶点到源点的距离标号int iter[maxn];//当前弧,在其之前的边已经没有用了void addedge(int from,int to,int cap)//向图中增加一条从from到to的容量为cap的边{ G[from].push_back((edge){to,cap,G[to].size()}); G[to].push_back((edge){from,0,G[from].size()-1});}void bfs(int s)//通过bfs计算从源点出发的距离标号{ memset(level,-1,sizeof(level)); queue<int>que; while(!que.empty()) que.pop(); level[s]=0; que.push(s); while(!que.empty()) { int v=que.front(); que.pop(); for(int i=0; i<G[v].size(); i++) { edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } }}int dfs(int v,int t,int f)//通过dfs寻找增广路{ if(v==t||f==0) return f; for(int &i=iter[v]; i<G[v].size(); i++) { edge &e=G[v][i]; if(e.cap>0&&level[v]<level[e.to]) { int d=dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0;}int max_flow(int s,int t)//求解从s-t的最大流{ int flow=0; for(;;) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,INF))>0) { flow+=f; } }}int main(){ int t,m,x,y,z,T=0; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); k=n; for(int i=0; i<=n; i++) G[i].clear(); for(int i=0; i<m; i++) { scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); } int ans=max_flow(1,n); printf("Case %d: %d\n",++T,ans); } return 0;}
3、Edmonds-Karp算法:算法详解参见博客http://blog.csdn.net/y990041769/article/details/21026445
Edmonds-Karp算法,即最短路径增广算法,简称EK算法。
其思路是每次找出一条从源到汇的能够增加流的路径,调整流值和残留网络 不断调整直到没有增广路为止
增广路: 增广路是这样一条从s到t的路径,路径上每条边残留容量都为正
把残留容量为正的边设为可行的边 那么我们就可以用简单的BFS得到边数最少的增广路
EK算法的思路非常的简单,就是一直找增广路径(BFS),假如有记录增广路的最小值k,ans+=k,并更新网络的值(要用反向边)。
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<vector>#include<queue>#define INF 0x3f3f3f3ftypedef long long LL;using namespace std;const int maxn=1008;struct edge{ int from,to,cap,flow; edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}};struct edmondskarp{ int n,m; vector<edge>edges; vector<int>mp[maxn]; int a[maxn]; int p[maxn]; void init(int n) { for(int i=0;i<n;i++) mp[i].clear(); edges.clear(); } void addedge(int from,int to,int cap) { edges.push_back(edge(from,to,cap,0)); edges.push_back(edge(to,from,0,0));//反向弧 m=edges.size(); mp[from].push_back(m-2); mp[to].push_back(m-1); } int Maxflow(int s,int t) { int flow=0; for(;;) { memset(a,0,sizeof(a)); queue<int>q; q.push(s); a[s]=INF; while(!q.empty()) { int x=q.front(); q.pop(); for(int i=0;i<mp[x].size();i++) { edge& e=edges[mp[x][i]]; if(!a[e.to]&&e.cap>e.flow) { p[e.to]=mp[x][i]; a[e.to]=min(a[x],e.cap-e.flow); q.push(e.to); } } if(a[t]) break; } if(!a[t]) break; for(int u=t;u!=s;u=edges[p[u]].from) { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; } flow+=a[t]; } return flow; }};int main(){ int t,n,m,T=0; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); edmondskarp ac; int x,y,z; ac.init(n); for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&z); ac.addedge(x,y,z); } int ans=ac.Maxflow(1,n); printf("Case %d: %d\n",++T,ans); } return 0;}题目描述:
Flow Problem
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 16308 Accepted Submission(s): 7694
For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)
23 21 2 12 3 13 31 2 12 3 11 3 1
Case 1: 1Case 2: 2
- 【网络流之最大流算法模板】HDUOJ 3549 Flow Problem
- hdu 3549 Flow Problem(最大流EK算法模板)
- HDU 3549 Flow Problem【最大流模板题,EK算法】
- HDU 3549 Flow Problem(网络流之最大流模板题)
- HDOJ-3549 Flow Problem (最大流模板)
- HDU 3549Flow Problem(网络流之最大流)
- HDU 3549 Flow Problem 最大网络流
- hdu 3549 最大网络流 Flow Problem
- HDU3549 - Flow Problem(模板网络流 + Ford-Fulkerson算法)
- HDU3549 Flow Problem 【网络流E-K算法模板】
- HDU 3549 Flow Problem (用一道最裸的最大流开启网络流算法之路)
- hdu3549 Flow Problem 最大流模板 isap
- hdu 3549 Flow Problem 最大流模板题 Ford-Fulkerson算法
- HDU 3549 Flow Problem(最大流+EK邻接表||邻接矩阵||dinic算法模板比较)
- 【最大流+模板题】杭电 hdu 3549 Flow Problem
- hdu 3549 Flow Problem(最大流模板题)
- [ACM] hdu 3549 Flow Problem (最大流模板题)
- HDU 3549 Flow Problem 最大流模板题
- JAVA代码获取MAC地址
- c++归并排序
- 点宏染整厂ERP生产管理系统介绍
- df和du显示的磁盘空间使用情况不一致的原因及处理
- 51keil与proteus联调,实现在线仿真
- 【网络流之最大流算法模板】HDUOJ 3549 Flow Problem
- 归并排序
- 设计模式之多例模式
- 自己配置的谷歌浏览器插件
- 设计编写用例注意事项
- Visual Studio C++/C 教你四步安装graphics图形库
- [原创] Nagios install Plugin check_iostat
- React Native 项目 常用 第三方组件 汇总(一)
- BurpSuite中的安全测试插件推荐