【算法•日更•第三十四期】最大流算法

▎写在前面

  在之前,我们已经清楚了网络流与最大流是什么,以及增广的操作。

  如果你还不会请点击学习。

  传送门

▎基本思路

  先放上一张图,要不然感觉有点空旷

  

  下方文字请结合上面的图片食用

  先来弄清楚一个概念:容许流,就是从源点到汇点的流,显然,一个图中的容许流不是唯一的,而最大流就是流量最大的容许流。

  我们先假设S是源点,T是汇点,为了寻找S到T的最大流,我们应该不断尝试寻找增流路径,增加容许流的流量,知道无法增加为止。这也被称为增广过程。

▎Ford-Fulkerson标号算法

  还是上面的图。

  我们对于一条边,记录三个值:这条边的容量,已用容量,剩余可用容量(不断增广时会消耗容量)。同时,再增加一个叫做反射弧反向弧的东西,初始全部为0,用于存储一条边(u,v)的逆向边(v,u),虽然不存在,但是可以用于反悔,以便于保证枚举到每一种情况。反向弧虽然名字特殊,但是我们把它视作普通的边。

  这个算法既然叫作标号算法,那么一定是要标号的,对于每个点,都会有两个标号:第一个是前驱(也就是从那里过来的),第二个是当前路径上的最小边权。

  这个算法本质上就是不断搜索,从S标号(无,inf)开始,不断扩展(权值为0的边不选择),到达另一个点,继续标号,如果到达了T,那么最大流加上第二个标号。而前驱的作用则是回溯,把路径上的边全部都减去该路径上的最小边权,同时该边的反向弧也增加最小边权。直到T无法再次被标号,则当前得到的容许流就是最大流。

▎算法图解

  首先放个图:

  

  然后从s开始标号。

  

  然后随便挑一条,走到1号点的位置,然后标号。

  

  接着走到T。

  

  然后发现已经到达了T,T已经被标过号了,于是最大流加1。

  

  然后返回,我们会发现(1,T)这条边减去1之后就是0了,那么为了简洁,我们就可以把它视作没有了,再添一条反向弧。(S,1)也是同理。

  

  接着我们用刚才的方法遍历S -> 2 -> T这条路径。

  

  发现标号了T,那么回溯,并且最大流加4。

  

  

  于是我们就发现无法标号T了,那么此网络的最大流就是1+4=5了。

▎算法的正确性

  虽然无法直接理解这个算法到底为什么正确,但是该有的条件它均已满足:

  ①每条边的长度都不可能是负数。

  ②每次增广时,都能保证每个点流量平衡。

  ③每一次S的出流量和T的入流量都变化相同。

  ④只要最大流是有限的,那么一定会在有限的时间内求出(不会死循环)。

posted @ 2019-08-06 15:11  c1714-gzr  阅读(406)  评论(0编辑  收藏  举报