poj 1273 最大流(Ford-Fulkerson算法和Dinic算法分别实现)
2014-07-10 16:45
441 查看
最大流模板题目
Ford-Fulkerson:
Dinic求最大流的过程:先利用 BFS对残余网络分层,此后从源点开始,用DFS从前一层向后一层反复寻找增广路(即要求DFS的每一步都必须要走到下一层的节点)。
(因此前面在分层时,只要进行到汇点的层次数被算出即可停止,因为按照该DFS的规则,和汇点同层或更下一层的节点,是不可能走到汇点的。)
DFS过程中,要是碰到了汇点,则说明找到了一条增广路径。此时要增加总流量的值,消减路径上各边的容量,并添加反向边,即进行增广。然后进行顶点回溯,到第一条仍有容量的边的顶点处继续找增广路。如果回溯到源点而且无法继续往下走了,DFS结束。
因此,一次DFS过程中,可以找到多条增广路径。DFS结束后,对残余网络再次进行分层,重复上述步骤。
当残余网络的分层操作无法算出汇点的层次(即BFS到达不了汇点)时,算法结束,最大流求出。一般用栈实现DFS,这样就能从栈中提取出增广路径。
Ford-Fulkerson:
#include <stdio.h> #include <string.h> #define N 202 int q ;//用于找增广路径的队列 int c ,f ;//c是路径的容量,f保存寻找过程中的流量 int a ,p ;//p存放一条增广路径的前一个结点 int n,m; int maxflow(int s,int t){//从s到t的最大流 int i,j,res = 0; int front,rear; while(1){ front = rear = -1; q[++rear] = s; memset(a,0,sizeof(a)); memset(p,0,sizeof(p)); a[s] = 0x3fffffff; while(front < rear){ i = q[++front]; for(j = 1;j<=n;j++) if(!a[j] && c[i][j]-f[i][j]>0){ a[j] = a[i]<c[i][j]-f[i][j]?a[i]:c[i][j]-f[i][j]; q[++rear] = j; p[j] = i; } } if(!a[t]) break; for(j = t;j!=s;j=p[j]){ f[p[j]][j] += a[t]; f[j][p[j]] -= a[t]; } res += a[t]; } return res; } int main(){ freopen("a.txt","r",stdin); while(scanf("%d %d",&m,&n)!=EOF){ int i,x,y,w; memset(c,0,sizeof(c)); memset(f,0,sizeof(f)); for(i = 0;i<m;i++){ scanf("%d %d %d",&x,&y,&w); c[x][y] += w; } printf("%d\n",maxflow(1,n)); } return 0; }
Dinic求最大流的过程:先利用 BFS对残余网络分层,此后从源点开始,用DFS从前一层向后一层反复寻找增广路(即要求DFS的每一步都必须要走到下一层的节点)。
(因此前面在分层时,只要进行到汇点的层次数被算出即可停止,因为按照该DFS的规则,和汇点同层或更下一层的节点,是不可能走到汇点的。)
DFS过程中,要是碰到了汇点,则说明找到了一条增广路径。此时要增加总流量的值,消减路径上各边的容量,并添加反向边,即进行增广。然后进行顶点回溯,到第一条仍有容量的边的顶点处继续找增广路。如果回溯到源点而且无法继续往下走了,DFS结束。
因此,一次DFS过程中,可以找到多条增广路径。DFS结束后,对残余网络再次进行分层,重复上述步骤。
当残余网络的分层操作无法算出汇点的层次(即BFS到达不了汇点)时,算法结束,最大流求出。一般用栈实现DFS,这样就能从栈中提取出增广路径。
#include <stdio.h> #include <string.h> #define INF 0x3fffffff #define min(a,b) a<b?a:b #define N 205 int n,m; int flow ,visited ,layer ,q ,stack ; int do_layer(int s,int t){//用队列对节点进行分层 int i,front,rear,now; front = rear = -1; memset(layer,-1,sizeof(layer)); q[++rear] = s; layer[s] = 0; while(front < rear){ now = q[++front]; for(i = s;i<=t;i++) if(layer[i]==-1 && flow[now][i]>0){ layer[i] = layer[now]+1; if(i == t) return 1; q[++rear] = i; } } return 0; } int dinic(int s,int t){//用堆栈模拟dfs int i,now,top=-1,aug,res=0,temp,vs,vt; while(do_layer(s,t)){ memset(visited,0,sizeof(visited)); stack[++top] = s; visited[s] = 1; while(top>-1){ now = stack[top]; if(now == t){ aug = INF;temp = 0;//temp保存回溯的位置 for(i = 1;i<=top;i++){//找本次增广的流量 vs = stack[i-1]; vt = stack[i]; if(aug>flow[vs][vt] && flow[vs][vt]>0){ aug = min(aug,flow[vs][vt]); temp = vs; } } res += aug; for(i = 1;i<=top;i++){//更新流量以及反向边 vs = stack[i-1]; vt = stack[i]; flow[vs][vt] -= aug; flow[vt][vs] += aug; } while(stack[top]!=temp){ visited[stack[top]] = 0; top--; } }else{ for(i = s;i<=t;i++) if(!visited[i] && flow[now][i]>0 && layer[i]==layer[now]+1){ stack[++top] = i; visited[i] = 1; break; } if(i > t) top--; } } } return res; } int main(){ freopen("a.txt","r",stdin); while(scanf("%d %d",&m,&n)!=EOF){ int i,a,b,w;; memset(flow,0,sizeof(flow)); for(i = 0;i<m;i++){ scanf("%d %d %d",&a,&b,&w); flow[a][b] += w; } printf("%d\n",dinic(1,n)); } return 0; }
相关文章推荐
- poj 1459 最大流算法(Dinic算法与Ford-Fulkerson算法)
- poj 1459 Power Network : 最大网络流 dinic算法实现
- [poj] 1273 Drainage Ditches[最大流][Ford-Fulkerson]
- POJ-1273-Drainage Ditches(最大流)dinic实现 后续模板待补充
- poj 1273 最大流 ford-fulkerson
- poj 1273 hdu 1532 网络流最大流 Dinic算法
- poj 1273 Drainage Ditches 【图论-网络流-最大流-Ford-Fulkerson】
- poj 1459 Power Network : 最大网络流 dinic算法实现
- poj1273--Drainage Ditches(最大流Edmond-Karp算法 邻接表实现)
- POJ 1273 最大流Ford-furkerson & Dinic
- poj 1273Drainage Ditches 最大流
- POJ 1273 求最大流(Edmond_karp模板题)
- POJ 1273 最大流
- poj 1273 Drainage Ditches--最大流--sap
- 【最大流】北大 poj 1273 Drainage Ditches
- POJ 1273 Drainage Ditches(最大流)
- poj 1273 Drainage Ditches ( 最大流--Edmonds_karp算法)
- POJ-1273(最大流-Augment Path,EK,BFS)
- poj 1273 EK 最大流
- POJ1273 Drainage Ditches——最大流