最大流:知识准备

网络流的来源和实际应用什么的自己跟度娘脑补去……网络流题目又分最大流、最小费用最大流、最小割等等,在这里只讲最大流(Maxflow),并且本文中涉及的知识仅为学习最大流算法所需,其他算法会在未来奉上。

一般的最大流模型(括号内以水管作为类比):图中有N个点和M条边,每条边有一个非负流量限制c(水管的大小限制了水的流量),并且有一个源点S(出水口)和汇点T(入水口),要求你求出从源点到汇点的最大流量。

首先需要知道这样几个定理(看了很多讲义都起流量守恒定理之类各种各样的名字,我觉得名字也没什么必要知道,就知道是什么、会做不就行了么):

1.对于每个不是源点和汇点的点i,进入i的流量必定等于从i流出的流量(水管里流进多少水就要流出多少水,总不能凭空蒸发吧)

2.对于每条边j,这条边上的流向总是小于等于它的流量限制,即Flow[j]<=MaxFlow[j](你总不能把水管撑爆了是不是)

知识准备:

1.增广路径:从S到T的一条可行路径,且每条边的流量都>0。一条增广路径上的流量(以下简称增广路流量)等于这条路上剩余流量(Q:为什么是剩余呢?A:先往下看再说。)最小的一条边的流量(就像一连串水管的水流量由其中最窄的一根水管决定)。

2.剩余图:又称残留图,残留网络。顾名思义,剩余图就是剩下还要继续搜索增广路的图。每次找到一条增广路后,将所有正向边(下一条就会提到反向边)的流量减去增广路流量,得到的一个更新后的图即为剩余图。

3.☆反向边☆:这是网络流问题最精华的一部分,有这样一句很精辟的解释深刻的指出了反向边的作用:

<span style="font-size:14px;">/*	反向边就是给了程序一次后悔的机会      */</span>

对于每条从u指向v的边E(u,v),建立一条从v指向u的边E'(v,u),其初始流量为0。每次找到一条增广路以后,将这条路上所有边的流量减去增广路流量,并将所有边的反向边的流量加上增广路流量。在增广路介绍中我们已经规定了如何修改正向边的值,现在又得出了反向边流量值的规定:等于正向边已经流过的流量,而正向边的流量为剩下还能流的流量。于是我们又得到了上面提到的一个相协调的值:初始时,正向边的流量为最大流量,反向边的流量为0。

那么如同上文所说,反向边是如何“给程序一次后悔的机会呢”?举个很经典的例子:

               图1

对于这个图,N=3,M=5,每条边的流量均为1.

我们在找增广路时可能会出现下图这种情况:

             图2

显然,这是一条可行的增广路,但是,当我们将增广路上的流量更新后,剩余图会变成这样:

              3

在这个图中,已经不存在增广路了,所以最大流=1,但是实际上:

                              4

按照这样走的最大流=2.很明显,我们的搜索是存在bug的(电脑:怪我咯?),但是这样的bug又是不可避免的,毕竟我们无法得到数据,那么问题来了:有没有办法可以“修复”这样的bug呢?好消息是有的。这个神奇的东西名字就叫反向边。在图3建立反向边以后,就变成图5(其余反向边已略去):

                 5

3->2这条边即为一条反向边,并且根据上文所提到的,由于正向边已经流了1个单位的流量,所以反向边的流量为1.然后我们会非常惊奇的发现,从1->3->2->4又找到了一条增广路,并且由于2->33->2都流了1个单位的流量可以相互抵消,我们所得到的结果和图4一模一样!

那反向边工作原理怎样描述呢?看了很多讲义都觉得讲的云里雾里的,自己想了一种路子应该挺好理解的:

                         图6

图6为一个网络流图的一部分,i->j为正向边,j->i为反向边,现在我们假设x1->i->y1和x2->j->y2这两条路是这个图中的最大流,但是如果我们第一次搜索增广路时错误的走了x1->i->j->y2怎么办?别担心,我们可以利用反向边,再走一条x2->j->i->y1的路径,此时flow(i->j)=flow(j->i),正反边上的流量可以抵消掉,这时我们就将第一条路径i以后的点和第二条路径j以后的点互换,又变成了x1->i->y1和x2->j->y2.那么推广到一般情况呢?i->j的流量为flow(i,j),j->i的流量为flow(j,i)(稍微思考一下就可以想到一定有flow(j,i)<=flow(i,j)),那么实质上,就可以合并为:从i->j的流量为flow(i,j)-flow(j,i),(不要真的在程序里面合并-_-只是这样理解)。

 

由此,我们总结了反向边的实质:

<span style="font-size:14px;">/*通过走反向边,来抵消正向边已经走过的流量,这样即使程序之前作出了一个错误的决策,也可以用反向边来退回一部分正向边的流量的目的,相当于“后悔”。*/</span>

Notice:

那有人会问:反向边实际应该是不存在的,走反向边难道就不会出错吗?我们可以看一下上文中反向边流量值的定义:等于正向边已经走过的流量,就相当于是正向边可以退回多少流量。因此反向边走了多少流量就等价于从正向边退回了多少流量,因此我们即使将反向边的流量全部用完,效果也只是将正向边的流量全部退回。由此可得,反向边值的定义就严格保证了它不会出错。

在图中,反向边和正向边一样都是可以走的边,没必要说什么再开一个数组存储然后特殊处理什么的,一开始图中没有任何流量,反向边流量值都为0,就算要走也走不了。所以,写程序时可以放心大胆的将正反边都建在一个图里。

 理解了基础知识,我们就可以着手学习最大流算法啦~猛戳这里☞http://blog.csdn.net/ycdfhhc/article/details/42580751

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值