首页 > 其他 > 详细

网络流小结

时间:2019-03-31 21:59:11      阅读:134      评论:0      收藏:0      [点我收藏+]

网络流小结

联赛过后,虽然遗憾的没拿到一等,但这不是止步不前的时候,于是我就学了学网络流,学了这几天,也该总结总结了......

网络流其实就是一种图论模型,在这种图中,边权变成了坑爹的流量,常见的最短路问题也变成了最大流-最小割问题

网络图和普通图的最大区别也就是边权不再是一个干干巴巴的数字,或者强赋意义的数量,而是真真正正地变成了一个具有实际意义的量—容量.我个人认为,这在现实中有着更广泛的应用,网络流量的分配,水流量的分配等诸多问题,都可以转化为这个模型,网络流具有十分广泛的应用,或许这也是它被称为图论的最高奥义的原因之一吧.

网络图的存储与普通的图并无太大不同,这也得益于邻接表这一巧妙的设计,我常用的存储方式是这样的:

struct edge {
    int to , next , flow ; // 意义与普通邻接表相同,flow就是"边权",也就是容量
} ;

就是这么一个结构体,当然这其中没有牵扯到费用,因为我还没学习最小费用最大流这类问题

而只知道如何存储是远远不够的,这只是一个小基础.网络流的第一步就是最大流问题,问题描述为:
对于一张只具有一个源点和一个汇点的网络,求出从源点到达汇点所能实现的最大流量.
这个问题与经典图论问题的区别显而易见,这时的边权/容量是一种限制,并且是可变的.而且,显然,对于一条路径的最大流,限制它的是它的最小弧容量.

一个很显然的思路是每次都尝试去在可行的范围内寻找还未满载的路径并使其达到最大流.这样一条未满载还可增加流量的路径称之为增广路.每次寻找增广路这个思路大的方向上是没有错的,事实上我们也正是这样做的.

但是,这样有一个很显然的问题,聪明的你一定已经想到了,那就是这会导致加入我们当前得到的可行流中的某一条弧属于一条更优的路径,那么这条更优的路径就会被阻塞而导致无法统计.而如果我们使用一贯的回溯思路来解决,那么复杂度就上升到了指数级,这种复杂度往往难以承受.

首先明确一个事实,从 \(u\) 流向 \(v\) 数值为 \(val\) 的流量 , 再从 \(v\) 流向 \(u\) 数值为 \(value\) 的流量等价于从 \(u\) 流向 \(v\) 的数值为 \(val-value\) 的流量
那么我们就需要一种设计,来使得不通过回溯也能完成所有可行流的统计.由此,我们对于一条弧 \((u,v)\) 建立它的反向弧 \((v,u)\) ,由于一开始并不能有任何的流量从 \(v\) 流向 \(u\) 所以一开始,反向弧的所有容量为0.每当我们正向流过 \(val\) 的流量,对应的反向弧就能反向流动 \(val\) 的流量.这种机制,正是 \(Edmond \: Karp\) 算法和 \(Dinic\) 算法的实现基础.反向弧的引入使得我们已经流过的流量有了流回来的机会,因此,它代替了回溯的作用.

那么一个非常自然的思路呼之欲出了:每次寻找一条增广路进行增广,最后统计出的答案就是最大流!
增广的过程也十分简单,把增广路径上所有的正向弧容量减去路径上最大的可行流,反向弧同时增大相应的容量即可

接下来的问题便是寻找增广路,一个很自然的想法是使用 \(bfs\) 或者 \(dfs\).而我们也确实是这么做的,只不过一般不使用 \(dfs\),它很容易变得很慢,于是我们就选用了喜闻乐见的 \(bfs\) ,稳定的 \(O(n)\) 复杂度相比较而言十分优秀.
明确了以上思路之后,就能得到一个正确也不太慢的最大流算法了,这就是\(Edmonds \: Karp\) 算法,简称 \(EK\) 算法.虽然正确性有了保障,而且也足以应付一些不太刁钻的数据,但它的复杂度是 \(O(n \times m^2)\) 的,十分的不理想.因此,我们需要一种更加优秀的算法,来保证时间复杂度.

To be continued......

网络流小结

原文:https://www.cnblogs.com/Equinox-Flower/p/10633382.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!