这段时间复习了下网络流模型,感觉比以前的理解有了长足进展,虽然我知道这东西难就难在建模上,而它的算法本身其实难度不大,但我还是决定说一些我的理解,毕竟理解了本质的东西运用起来才会更灵活。

最大流的求解一般有两类算法(用费用流附带求出的不列入考虑范围),就是增广路(FF)系列和预流推进(PF)系列。在很多地方都看到推荐使用后者,因为效率更高,但其实不然,今天我这篇文章就是要重点介绍前者,相信大家看了过后也会喜欢它的。

首先,那些一大堆的关于网络的定义我就不说了,不明白的就先去看看书好了,我们约定S是源,T是汇,G表示残余图。增广路算法其实相当好理解,因为只要在G中存在一条从S到T的通路,那沿这条路走,流量一定还可以增加,所以当求得最大流的时候一定不存在S-T通路。 那反过来成立么?显然,因为我们有最小割最大流定理,所以由此就得到了FF算法的基本方法:

不断的在G中找一条S-T通路,然后沿其增广,直到无法找到。

至于用什么方法去找一条路,那就随便了,BFS,DFS,甚至A*,你可以把你能想到的方法试个遍,看看哪个合胃口就用哪个吧。

注意那个用BFS的方法,它的官方名字叫Edmonds-Karp(EK),它和我们后面要说的费用流有很大的关系,这里先简单提示一下。

那这方法的复杂度呢?如果是整数流(事实上分数流的话可以构造数据让FF无法停止,这时候必须用到PF的方法),显然每次至少增广1的流量,每次查找O(E)条边,增广要O(V)的时间,因此复杂度为O((m+n)*U),U是最大流。

听上去很恐怖,其实EK算法的一个稍微精确的上界是O(VE^2),还是很夸张。

那么,怎样才能跑得更快呢?想想,每次用BFS求出的Shortest Path Tree(SPT),我们只关心了S-T最短路,其实还有很多信息没有利用到,那么如果求一次SPT,我们可以增广多次的话,是不是会好些??

于是,引入层次图的概念,说通俗点,就是求G的SPT,把G中每个顶点的距离S的标号d给求出来,保留所有的s->t中d[s]+1=d[t]的边(注意可以不是SPT中的边),最后再在层次图中用多次BFS把所有的增广路求出来增广。

这样看似更快了,其实没有,因为分析复杂度依然是O(VE^2),没有改进,而且我们还要写更多的代码。那瓶颈在哪里呢?对了,就是那步在层次图中用BFS来找增广路。其实更好的方法是用DFS,一次就可以把所有的增广路求出来,具体做法如下:

从S开始做DFS,一旦发现一条增广路,于是就沿其增广,然后DFS回退到离S最近的一条满流的边的起点处,并在图中删除该边的终点,继续搜索。

上面的算法就是著名的Dinic算法,它的复杂度为O(EV^2)(注意,看清楚2的位置),对于密图有不小的改进。

事实上,我非常推荐在各类比赛中用Dinic算法,因为它实现简单,而且实际运行速度快,比起PF算法好写太多了!!

那单纯的说好还是不行,要拿出依据来。关于PF算法的理论在本文中就不详细叙述了,可能以后我会专门介绍它。一般的PF实现是O(V^4)的,而Relable-To-Front是O(V^3),高标推进据称是O(V^2*sqrt(E)),虽然它实际中确实比较快,但是PF的算法都有一个缺点,就是必须加启发优化,至少是Gap优化,否则实际中会比较慢。因此,写一个PF的代码自然就比较多了。

上面基本上把最大流的算法盘点了一下,下面还是说一下最小费用流问题。

如果一个网络的边不仅有容量,还有单位流量费用的话,那我们自然想在求得最大流的同时,使总费用更低。因此,最小费用流实际上是一个更通用的模型,因而其应用也更广。

令 人惊奇的是,解决该问题可以不需要先求出最大流来(当然也有方法需要),所以如果你不想记那么多算法的话只知道该算法也没问题。因为费用流的算法如果说复 杂的话可以把线性规划扯近来,所以先罗列下几个基本方法,然后介绍最简单的一种,其它的如果你有兴趣可以自己找文章来看:

1 连续最短路算法(Successive Shortest Path);

2 消圈算法(Cycle Canceling);

3 原始对偶算法(Primal Dual);

4 网络单纯形(Network Simplex)。

后面的两个分别是前面两个的高级优化版本,其基本的优化思路就是和我们上面论述的优化增广类似,就是希望每次都能做几次运算,不要一次用了就丢弃了。最好用的就是第一个方法,方法二在Algorithm in C图论部分有详细论述,我就不说了。

还记得刚才我说的EK么?其实如果我们用Dijkstra在G中找S-T最短路,而不是BFS的话,是不是就解决问题了呢?是的,完全正确,我把证明留给大家想,其实很简单。

但是,有个问题,在G中存在负权的边,用Dijkstra是不是不行了呢?非要用Bellman-Ford么?其实不然,只要原图中没有负环存在(有的话不存在最小费用),那么我们可以利用Johnson算法的重赋权技术把所有的边先变成正权,然后以后每次增广后再维护一下不就可以用高效的Dijkstra了?算法如下:

用Bellman-Ford求各点到S的高度标号d[];

以后每求一次最短路,设标号为pi[],那么执行:

For i=1 to v do

d[v]+=pi[v]

这样一来,标号就一直合法了(具体证明还是留给大家吧)。

好了,说这么多理论,下篇文章将会说几个具体的题目,加深对算法的理解。

转载于:https://www.cnblogs.com/zen_chou/archive/2009/07/16/1525185.html

【转载】网络流和最小费用流相关推荐

  1. [转载]acm进阶之路

    第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码, 因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打  出来.  1.最短路(Floyd ...

  2. (转载)ACM训练计划,先过一遍基础再按此拼搏吧!!!!

    ACM大量习题题库 ACM大量习题题库  现在网上有许多题库,大多是可以在线评测,所以叫做Online Judge.除了USACO是为IOI准备外,其余几乎全部是大学的ACM竞赛题库. USACO h ...

  3. 基础省选+NOI 第9部分 网络流

    1.二分图匹配 算法竞赛入门经典训练指南+陈锋+ch5.5_二分图的匹配 算法竞赛入门经典训练指南+陈锋+ch5.5_二分图的匹配_哔哩哔哩_bilibili SWPU-ACM每周算法讲堂-匈牙利算法 ...

  4. NOI图论算法:网络流

    网络流 https://www.bilibili.com/video/BV15p4y1C7zW https://www.bilibili.com/video/BV1HE411Y7sM https:// ...

  5. 做acm 需要学的算法

    做acm 需要学的算法 转一个搞ACM需要的掌握的算法.  要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.  适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什 ...

  6. ACM 中常用的算法有哪些?

    在网上看到别人ACM学习的心得,转载过来,源地址不记得了,当时是百度的.内容如下: 网络上流传的答案有很多,估计提问者也曾经去网上搜过.所以根据自己微薄的经验提点看法. 我ACM初期是训练编码能力,以 ...

  7. ACM 中常用的算法有哪些? 2014-08-21 21:15 40人阅读 评论(0) 收藏...

    ACM 中常用的算法有哪些?作者: 张俊Michael 网络上流传的答案有很多,估计提问者也曾经去网上搜过.所以根据自己微薄的经验提点看法. 我ACM初期是训练编码能力,以水题为主(就是没有任何算法, ...

  8. 从今开始,好好学习一下算法!

    ACM 进阶之路(转) 2007年12月30日 星期日 18:20 一般要做到50行以内的程序不用调试.100行以内的二分钟内调试成功.ACM主要是考算法的,主要时间是花在思考算法上,不是花在写程序与 ...

  9. POJ题目分类(按初级\中级\高级等分类,有助于大家根据个人情况学习)

    本文来自:http://www.cppblog.com/snowshine09/archive/2011/08/02/152272.spx 多版本的POJ分类 流传最广的一种分类: 初期: 一.基本算 ...

最新文章

  1. 首批新冠肺炎人体疫苗来了!全球第一mRNA药物研发公司研制,已开启安全性临床试验...
  2. java中 抽象类+接口
  3. 毒瘤题No.006-byFHS
  4. linux查看usb设备文件,linux – 确定USB设备文件路径
  5. docker中部署mysql
  6. 【Eclipse】将控制台输出直接保存到文本文件
  7. c语言1000内亲密对数,《C语言程序的设计上机指导》项目五函数及其应用.pptx
  8. 书籍推荐(2016-2020)--统计数学计算机为主,心理学为辅
  9. Linux有关信息收集命令
  10. java的编译器怎么出来_怎样掌握ava编译器的使用,教程在这里,如何进行Java初级学习...
  11. 基于9款CSS3鼠标悬停相册预览特效
  12. python如何修改代码_不修改代码打包python机器学习工程
  13. linux删除的文件有回收站么,Linux命令行删除文件到回收站
  14. rabbitmq视频教程,面试官:
  15. 【等保】二级等保常见问题解答汇总
  16. 利用GitHub搭建个人网站
  17. 小米网卡驱动linux,小米笔记本pro 15.6寸安装ubuntu16.04无法使用wifi的解决方法
  18. LoadRunner-登陆web tours订票网站,预订一张机票后退出-1
  19. Foxmail:完美配置QQ邮箱、163邮箱、Google邮箱
  20. 刘宇辰java_大家帮忙取名字啊

热门文章

  1. c语言grade d10,《电子技术10级C语言课程设计报告书写规范》.doc
  2. c++ 向量的值逆序输出_C++中vector的常用方法
  3. LeetCode面试题03. 数组中重复的数字
  4. qpsk 锁相环_本科毕业设计课题—QPSK相干解调的MATLAB仿真(4)
  5. 径向基函数RBF三维网格变形
  6. 数据库表操作、数据类型及完整性约束
  7. 老男孩爬虫实战密训课第一季,2018.6,初识爬虫训练-实战1-爬取汽车之家新闻数据...
  8. liunx驱动----异步通知
  9. Dynamics CRM 访问团队的使用
  10. cocos2d-x 帧动画