Edmonds_Karp 算法 (转)

找了好久终于在这个牛这里找到为什么反向边要加回流量的原因了,

因为是初学教程,所以我会尽量避免繁杂的数学公式和证明。也尽量给出了较为完整的代码。

本文的目标群体是网络流的初学者,尤其是看了各种NB的教程也没看懂怎么求最大流的小盆友们。本文的目的是,解释基本的网络流模型,最基础的最大流求法,即bfs找增广路法,也就是EK法,全名是Edmond-Karp,其实我倒是觉得记一下算法的全名和来历可以不时的拿出来装一装。

比如说这个,EK算法首先由俄罗斯科学家Dinic在1970年提出,没错,就是dinic算法的创始人,实际上他提出的也正是dinic算法,在EK的基础上加入了层次优化,这个我们以后再说,1972年Jack Edmonds和Richard Karp发表了没有层次优化的EK算法。但实际上他们是比1790年更早的时候就独立弄出来了。

你看,研究一下历史也是很有趣的。

扯远了,首先来看一下基本的网络流最大流模型。

有n个点,有m条有向边,有一个点很特殊,只出不进,叫做源点,通常规定为1号点。另一个点也很特殊,只进不出,叫做汇点,通常规定为n号点。每条有向边上有两个量,容量和流量,从i到j的容量通常用c[I,j]表示,流量则通常是f[I,j]。通常可以把这些边想象成道路,流量就是这条道路的车流量,容量就是道路可承受的最大的车流量。很显然的,流量<=容量。而对于每个不是源点和汇点的点来说,可以类比的想象成没有存储功能的货物的中转站,所有”进入”他们的流量和等于所有从他本身”出去”的流量。

把源点比作工厂的话,问题就是求从工厂最大可以发出多少货物,是不至于超过道路的容量限制,也就是,最大流。

比如这个图。每条边旁边的数字表示它的容量。


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

首先,假如所有边上的流量都没有超过容量(不大于容量),那么就把这一组流量,或者说,这个流,称为一个可行流。一个最简单的例子就是,零流,即所有的流量都是0的流。

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

这样我们就得到了一个更大的流,他的流量是之前的流量+delta,而这条路就叫做增广路。

我们不断地从起点开始寻找增广路,每次都对其进行增广,直到源点和汇点不连通,也就是找不到增广路为止。当找不到增广路的时候,当前的流量就是最大流,这个结论非常重要。

寻找增广路的时候我们可以简单的从源点开始做bfs,并不断修改这条路上的delta量,直到找到源点或者找不到增广路。

这里要先补充一点,在程序实现的时候,我们通常只是用一个c数组来记录容量,而不记录流量,当流量+1的时候,我们可以通过容量-1来实现,以方便程序的实现。

Bfs过程的半伪代码:下面另给一个C++版的模板

int BFS()
{
    int i,j,k,v,u;
    memset(pre,-1,sizeof(pre));
    for(i=1;i<=n;++i)flow[i]=max_int;
    queue<int>que;
    pre[start]=0;
    que.push(start);
    while(!que.empty())
    {
        v=que.front();
        que.pop();
        for(i=1;i<=n;++i)
        {
            u=i;
            if(u==start||pre[u]!=-1||map[v][u]==0)continue;
            pre[u]=v;
            flow[u]=MIN(flow[v],map[v][u]);
            que.push(u);
        }
    }
    if(flow[end]==max_int)return -1;
    return flow[end];
}

但事实上并没有这么简单,上面所说的增广路还不完整,比如说下面这个网络流模型。

我们第一次找到了1-2-3-4这条增广路,这条路上的delta值显然是1。于是我们修改后得到了下面这个流。(图中的数字是容量)

这时候(1,2)和(3,4)边上的流量都等于容量了,我们再也找不到其他的增广路了,当前的流量是1。

但这个答案明显不是最大流,因为我们可以同时走1-2-4和1-3-4,这样可以得到流量为2的流。

那么我们刚刚的算法问题在哪里呢?问题就在于我们没有给程序一个”后悔”的机会,应该有一个不走(2-3-4)而改走(2-4)的机制。那么如何解决这个问题呢?回溯搜索吗?那么我们的效率就上升到指数级了。

而这个算法神奇的利用了一个叫做反向边的概念来解决这个问题。即每条边(I,j)都有一条反向边(j,i),反向边也同样有它的容量。

我们直接来看它是如何解决的:

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

我们来看刚才的例子,在找到1-2-3-4这条增广路之后,把容量修改成如下

这时再找增广路的时候,就会找到1-3-2-4这条可增广量,即delta值为1的可增广路。将这条路增广之后,得到了最大流2。

那么,这么做为什么会是对的呢?我来通俗的解释一下吧。

事实上,当我们第二次的增广路走3-2这条反向边的时候,就相当于把2-3这条正向边已经是用了的流量给”退”了回去,不走2-3这条路,而改走从2点出发的其他的路也就是2-4。(有人问如果这里没有2-4怎么办,这时假如没有2-4这条路的话,最终这条增广路也不会存在,因为他根本不能走到汇点)同时本来在3-4上的流量由1-3-4这条路来”接管”。而最终2-3这条路正向流量1,反向流量1,等于没有流量。

这就是这个算法的精华部分,利用反向边,使程序有了一个后悔和改正的机会。而这个算法和我刚才给出的代码相比只多了一句话而已。

至此,最大流Edmond-Karp算法介绍完毕。接下来会介绍效率更高的dinic算法,最小割,最小费用最大流等内容。敬请期待。

转载于:https://www.cnblogs.com/dchipnau/archive/2011/09/16/4985966.html

网络流 增广路 入门很好的文章相关推荐

  1. 网络流 增广路 回退

    增广路: 有流量标记: 流量变化: 转载于:https://www.cnblogs.com/cmyg/p/9568904.html

  2. 网络流—Edmonds-Karp 最短增广路算法(最大流)

    网络流----Edmonds-Karp 最短增广路算法 ■求最大流的过程,就是不断找到一条源到汇的路径,然后构建残余网络,再在残余网络上寻找新的路径,使总流量增加,然后形成新的残余网络,再寻找新路径- ...

  3. 【网络流】解题报告:luogu P2740 [USACO4.2]草地排水Drainage Ditches(Edmonds-Karp增广路,最大流模板)

    题目链接:草地排水 若一条从源点到汇点的路径上各条边的剩余容量都大于0,则称这条路径为一条增广路. Edmonds-Karp增广路的策略就是不断用bfs寻找增广路,直至网络中不在存在增广路为止. 在每 ...

  4. 最短增广路Isap算法 网络流

    最短增广路 请先理解 bfs的求增广路的算法,再来学习Isap算法 最短增广路Isap算法 图片来源 <趣学算法>人民邮电出版社 陈小玉 /* 最短可增广路:重贴标签算法Isap 算法设计 ...

  5. XJOJ - 选信封(离散化+增广路)

    题目链接:点击查看 题目大意:Dumbulidone和Euphemia玩一个挑卡片游戏. Dumbulidone会给出N对信封,每个信封里有两张不同颜色的卡片,她会让Euphemia从中挑选任意个信封 ...

  6. 网络最大流中一般增广路算法(标号法)

    网络最大流主要有两大类求解方法:增广路算法和预流推进算法 一般增广路算法:主要分为初始流为零流和初始流为非零流的情况!后者在标号的时候注意一条边是正向连接还是反向连接:若是反向的连接,那么在调整的时候 ...

  7. 二分图前期基础之增广路

    二分图前期基础之增广路 刚开始学习的时候,总是受困于增广路径,不明白增广路径是如何应用以及其具体的含义是什么,感谢博客https://www.cnblogs.com/logosG/p/logos.ht ...

  8. hdu 1281(二分图匹配+增广路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 解题思路: 把棋盘的行x看成二分图左边的点,列y看成二分图右边的点,那么就把可以放车的位置看成是 ...

  9. 增广路算法 (最大流问题)

    Edmonds-Karp算法: 计算机科学中, Edmonds–Karp算法通过实现Ford–Fulkerson算法来计算网络中的最大流,其时间复杂度为O(V E2). 该算法由Yefim (Chai ...

  10. SAP和ISAP(网路最大流的两个增广路算法)

    ISAP是对SAP进行优化后的算法,ISAP时间复杂度为O(V^2E),SAP的时间复杂度为O(VE^2) SAP #include <iostream> #include <alg ...

最新文章

  1. 白嫖我常用的 11 个超火的前端必备在线工具,终于有时间上班摸鱼了
  2. Hadoop MapReduce V2 Yarn——WordCount
  3. U-BOOT之一:BootLoader 的概念与功能
  4. 【牛客 - 551E】CSL 的魔法(贪心,思维,STLmap,分块)
  5. java中的throw_Java中的throw和throws之间的区别
  6. 计算机网络带宽是什么意思,网络带宽是怎么计算的?
  7. 数据可视化大屏设计经验分享 【进阶篇】
  8. Emacs + gdb单步调试汇编代码
  9. 星球大战 BZOJ 1015
  10. 数据分析侠A的成长故事
  11. 基于单片机和C语言的毕业设计,毕业论文基于51单片机的C语言程序设计实训100例(1)(喜欢就下吧)...
  12. LBP特征及其一些变种
  13. PX4飞控学习与开发(六)-利用 VScode 修改源码
  14. 唐宋边塞诗词中的古灵州
  15. java菜鸟快速上手指南
  16. Flutter listview下拉刷新 上拉加载更多 功能实现
  17. 报错:Entering emergency mode. Exit the shell to continue 解决
  18. IBM X3400 m3 EFI platform initialization
  19. java传递指针_Java:通过指针传递参数
  20. 员工到管理者的四点转变|智测优测总结

热门文章

  1. 流水线机制、滑动窗口协议、GBN、SR
  2. 二十三、常用的标签:见源码
  3. 学习是一件高尚而孤独的事情
  4. unity3d ppsspp模拟器中的post processing shader在unity中使用
  5. java简单的数据库查询(SQLServer数据库)
  6. 关于 free 命令显示内存使用情况问题
  7. apache支持.htaccess
  8. 杭电多校HDU 6586 String(预处理 + 贪心)题解
  9. Fragment真正的完全解析(上)
  10. 关于Android屏幕适配