描述一下我实现的办法,顺便为自己打草稿了.
1.输入每对顶点间的容量,如果不存在边或者没有这个方向的边,容量为0
2.初始化所有点对之间的容量为0.
3.循环查找增广路径. (广度搜索)
方法是:
为每个顶点设置2个前驱域,一个是前驱结点,一个是目前路径上最小残留,在搜索中生成这些信息.
搜索过程中,边搜边计算活结点的邻接边的残留,是用c(u,v)-f(u,v),直接计算,不用做判断,结果>0则加入路径,=0则不加入.
搜索到汇点之后,根据前驱结点,最小残留,对路径上的边,如果c(u,v)>0,则f(u,v)+残留,f(v,u)-残留.
如果c(u,v)=0,则f(u,v)+残留,f(v,u)-残留. 意思也是不用判断,直接运算.
重复上述,至没有增广路径.
第一次看是很久前,一堆证明,蒙了.
第二次看是很久之前之后,耐心全看了一遍,证明基本看不进去,了解最大流是在干什么.
第三次看前几天,想学最大二分匹配,了解到有匈牙利这个大家都说很简单的算法...于是直接看导论最大二分匹配部分,没发现什么联系- -.
第四看,中午看到litaoye说学会最大流就是算法入门水平了,非常迫不及待. ..下午躺在床上,最大流从头看起. 看到二分匹配之前...感悟颇多...证明全懂了,就是广搜对算法的优化的大片证明得最后那里稍微模糊一点...
先谈谈感触,高人们别吝啬啊,帮忙看看我应该怎么深入到实践(实现算法)中.
1.以前看就因为1,2个地方不懂,导致往后都不懂,即便坚持看下来也没有收获.
总结以前卡住的地方有:
1. 流图,残留图, 它们是干什么的,怎么那么多数...
2. 流图,残留图,它们怎么联系在一起的...
3. 把最大流,最小割原理没弄懂,结果学起来就感觉没底气,连道理都不讲怎么学.(很直接的就是增广路径的理解与流图残留网络的关系理解)
自己解决了上述问题:
1. 对于一个流图, 对每条边E(u,v),有一个容量c(u,v),还有目前流过它的流,f(u,v). 残留网络就是对流图中每条边求 c(u,v)-f(u,v),表示还可以流过多少,这个值也讲作为找增广路径时要用的图(即残留网络.). 以前卡住,很大原因是对于流守恒性质的f(u,v)=-f(v,u)的作用很难理解... 因为算法导论上并没有画出负的流,以至于迷茫了很久很久...
还有容量,算法导论中流图上画出来的有向边都是具有容量的边,比如c(u,v)>0,那么有一个u->v的有向边,而记c(v,u)是0.
但这并不影响残留网络的生成与增广路径的计算.具体的用第二个问题描述.
2.假设流图已经存在,并且已经有了一些流,那么对所有的点对(u,v)及(v,u),计算c(u,v)-f(u,v)(c(v,u)-f(v,u)),如果E(u,v)存在,那c(u,v)就是c(u,v),而且f(u,v)>0. 如果不存在,那c()=0,f(v,u)=-f(u,v)<0; 对所有的N*N个点对,都计算出这个值,就是残留网络的边了。
(我认为实现时不能这样,直接在流图中边找增广路径边计算这个值就可以了,这个值大于0则可以走,=0则不可以走)
然后,在残留网络中,找一个从s到t的路径p, 并取路径上残留流量最小的那个流量,给所有的路径上的边的流量加上这个残留最小流量(叫残流吧。。)。即,假设(u,v)是从s到t增广路径上的一条边,那么就给f(u,v)+残流,给f(v,u)-残流。(这里当时也是卡住了,现在理解意义所在了)。 至此结束,然后在计算残流网络,再找增广路径。。一直到找不到增广路径为止。。。
3.假设流图中已经有了一些流量,那么对图任意割, 路径上的流量和都相等(反向边的流量是负值), 容量不一定相等。
那一定存在一个最小容量割来限制流量总和不能超越这个限制。。。
以上就是理解,大家帮忙看看有错没。 另外,我想先自己实现一下这个算法,用广搜的方法。
实现起来,我就用记录每个结点的前驱与前驱之前的最小残留,找增广路径的同时计算残留网,找到路径后,根据前驱回溯上去,对每个顺序走来的边(u,v)的流加上最小残留,对(v,u)的流减去最小残留。
以下是预流推进,进入队列的结点必须是溢出点,不能是汇点与源点.