给定一个有向图G=(V,E),把图中的边看作

管道,每条边上有一个权值,表示该管道

的流量上限。给定源点s和汇点t,现在假设

在s处有一个水源,t处有一个蓄水池,问从

s到t的最大水流量是多少?

网络流图里,源点流出的量,等于汇点流

入的量,除源汇外的任何点,其流入量之

和等于流出两之和。

下面我们来考虑如何求最大流。

首先,假如所有边上的流量都没有超过容量(水管),那么就把这个流,称为一个可行流。易见,任一网络中都有一个零流,即每弧a上f(a)=0的流f.

我们就从这个零流开始考虑,假如有这么一条路,这条路从源点开始一直一段一段的连到了汇点(这条路叫做可行路径),并且,这条路上的每一段都满足流量<容量,注意,是严格的<,而不是<=。那么,我们一定能找到这条路上的每一段的(容量-流量)的值当中的最小值delta。我们把这条路上每一段的流量都加上这个delta,一定可以保证这个流依然是可行流,这是显然的。

这样我们就得到了一个更大的流,他的流量是之前的流量+delta,而这条路就叫做增广路。我们不断地从起点开始寻找增广路,每次都对其进行增广,直到源点和汇点不连通,也就是找不到增广路为止。当找不到增广路的时候,当前的流量就是最大流。但这个想法是否正确?

考虑上面这样的图,如果我们沿着s-a-b-t路线走仅能得到一个100的流,实际上此图存在流量为200的流(sat+abt).问题出在过早地认为边a → b上流量不为0,因而“封锁”了流量继续增大的可能。

一种解决方法是在第一次找到增广路之后,在把路上每一段的容量减少delta的同时,也把每一段上的反方向的容量增加delta。即在Dec(c[x,y],delta)的同时,inc(c[y,x],delta)

第一次找到增广路:

第一次找到增光路添加反向边后得到的新图:



这样我们第二次搜索的时候就可以在新的网络里找到新的路径这是一个取消流的操作也可以看作是两条路径的合并。

第二次搜索又找到了一个流量为100的流,加上第一次搜索得到的流量为100的流,总流量上升到200

再对第二次搜索后的图添加反向边,变成:



在此图上再次进行dfs,已经找不到路径了,所以流量无法再增加,最大流就是200

在找增广路的时候采用广度优先的思想,我们就叫它EdmondsKarp算法。他是Ford&Fulkerson算法的改进。下面以一个题目为例给出代码:

poj1273

题目大意:

现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.

输入:

5 4

1 2 40

1 4 20

2 4 20

2 3 30

3 4 10

输出:

50

#include<bits/stdc++.h>
using namespace std;
const int maxn=205;
const int inf=0x7fffffff;
int r[maxn][maxn]; //残留网络,初始化为原图
bool visit[maxn];
int pre[maxn];
int m,n;
bool bfs(int s,int t) //寻找一条从s到t的增广路,若找到返回true
{
int p;
queue<int > q;
memset(pre,-1,sizeof(pre));
memset(visit,false,sizeof(visit));
pre[s]=s;
visit[s]=true;
q.push(s);
while(!q.empty())
{
p=q.front();
q.pop();
for(int i=1;i<=n;i++)
{
if(r[p][i]>0&&!visit[i])
{
pre[i]=p;
visit[i]=true;
if(i==t) return true;
q.push(i);
}
}
}
return false;
}
int EdmondsKarp(int s,int t)
{
int flow=0,d,i;
while(bfs(s,t))
{
d=inf;
for(i=t;i!=s;i=pre[i])
d=d<r[pre[i]][i]? d:r[pre[i]][i];
for(i=t;i!=s;i=pre[i])
{
r[pre[i]][i]-=d;
r[i][pre[i]]+=d;
}
flow+=d;
}
return flow;
} int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
int u,v,w;
memset(r,0,sizeof(r));///
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
r[u][v]+=w;
}
printf("%d\n",EdmondsKarp(1,n));
}
return 0;
}

最大流EK算法的更多相关文章

  1. 二分图的最大匹配——最大流EK算法

    序: 既然是个图,并且求边数的最大值.那么这就可以转化为网络流的求最大流问题. 只需要将源点与其中一子集的所有节点相连,汇点与另一子集的所有节点相连,将所有弧的流量限制置为1,那么最大流 == 最大匹 ...

  2. 最大流EK算法/DINIC算法学习

    之前一直觉得很难,没学过网络流,毕竟是基础知识现在重新来看. 定义一下网络流问题,就是在一幅有向图中,每条边有两个属性,一个是cap表示容量,一个是flow 表示流过的流量.我们要求解的问题就是从S点 ...

  3. 最大流——EK算法

    一.算法理论 [基本思想] 反复寻找源点s到汇点t之间的增广路径,若有,找出增广路径上每一段[容量-流量]的最小值delta,若无,则结束.在寻找增广路径时,可以用BFS来找,并且更新残留网络的值(涉 ...

  4. (通俗易懂小白入门)网络流最大流——EK算法

    网络流 网络流是模仿水流解决生活中类似问题的一种方法策略,来看这么一个问题,有一个自来水厂S,它要向目标T提供水量,从S出发有不确定数量和方向的水管,它可能直接到达T或者经过更多的节点的中转,目前确定 ...

  5. vector实现最大流EK算法

    序: 在之前的文章中实现了不利用STL实现EK算法,效率也较高.这次我们企图简化代码,减少变量的使用与手写模拟的代码. 注意:vector等STL的container在不开O2优化的时候实现同一个效果 ...

  6. 最大流EK算法模板

    最近学了下最大流算法,大概思想算是懵懵懂懂了,现在想把模板记录下来,以备后面深刻学习之用. #include<cstdio> #include<cstring> using n ...

  7. POJ-1459(最大流+EK算法)

    Power Network POJ-1459 这题值得思索的就是特殊的输入,如何输入一连串字符.这里采用的方法是根据输入已知的输入格式,事先预定好要接受的数据类型. 这里套用的板子也是最大流的模板,但 ...

  8. 【转】最大流EK算法

    转自:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 图-1 如图-1所示,在这个运输网络中,源点S和汇点T分别是1,7 ...

  9. POJ1273 最大流 EK算法

    套了个EK的模板 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdi ...

随机推荐

  1. facebook面试题【转】

    1. 给两个类A和Bclass A {public void foo (A a) { ...}}class B extends A {public void foo (B b) { ...}}问这么写 ...

  2. 网络数据嗅探工具HexInject

    网络数据嗅探工具HexInject   网络数据嗅探是渗透测试工作的重要组成部分.通过嗅探,渗透人员可以了解足够多的内容.极端情况下,只要通过嗅探,就可以完成整个任务,如嗅探到支持网络登录的管理员帐号 ...

  3. javascript对象初探 (五)--- 函数对象的属性

    与其他对象相同的是,函数对象中也有一个叫做constructor的属性,其引用就是Function()这个构造函数. function her(a){ return a; } console.log( ...

  4. 临远的activiti教程

    1. 简介 协议 下载 源码 必要的软件 JDK 6+ Eclipse Indigo 和 Juno 报告问题 试验性功能 内部实现类 2. 开始学习 一分钟入门 安装Activiti 安装Activi ...

  5. install nfs and share file

    介绍一下NFS的安装,以及共享文件 NFS(Net File System),通过使用NFS,可以像使用本地文件一样访问远程文件. 它主要解决了数据共享的问题,可以备份容灾. 安装配置 1.以linu ...

  6. sql的一些知识

    查询 查询表中的所有列(所有信息) SELECT * FROM userinfo 查询某一列(指定) select name from userinfo 查询某一列(指定,去重) SELECT DIS ...

  7. java多个文件压缩下载

    public static void zipFiles(File[] srcfile,ServletOutputStream sos){ byte[] buf=new byte[1024]; try ...

  8. Android学习系列(二)布局管理器之线性布局的3种实现方式

    转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39643669 LinearLayout是Android控件中的线性布局控件,它包括的子控件 ...

  9. 关于angular JS 中$timeOut 的一些不正常情况下的$destory

    最近项目中存在的问题头疼脑热了好一会. 我先简单说明下问题是由,使用$timeOut循环调用的时候由于页面存在异步加载会出现反复执行循环反复调用$timeOut,怎么清除跳出循环都不管用.于是查到了如 ...

  10. ubuntu 下的中文输入法的安装和配置- ibus

    ibus输入法 Chinese语言包安装 首先需要给Ubuntu16.04安装Chinese语言包支持.  如上图点击其中的Install/Remove Languages…,这个对话框是通过syst ...