什么是流网络
流网络是一种特殊的单向有权连通图。有且只有一个源点和汇点,权重作为容量。
图中a点是源点,也就是起点,一般记作s,f是汇点,也就是终点,一般记作t。
通过以上流网络衍生出来的,满足每条边的容量约束并且每个节点流入流出的流量守恒的图成为一个流(Flow)。
最大流问题就是求解给定流网络的最大流量配置,也就是怎样分配每天表上的流量能让源点到汇点的流量最大。上面在个流就不最大流,下面的流是最大流。
Ford-Fulkerson算法是求解最大流的常用算法,具体步骤如下:
首先将流网络复制两份,一份所有权重清零,用作记录当前求得的流,另一方完全复制原始网络,成为残存网络。
在当前残存网络中用BFS或DFS搜出任意一条从源点到汇点的路径,成为增广路径,路径的流量使用组成这条路径所有边的最小流量,也就是瓶颈或短板。然后把这条路径的流量叠加到当前流中,同时在残存网络中减掉。
继续在更新后的残存网络中搜索增广路径,直到无法搜到新的路径,因为部分关键边的容量已经用尽。这个时候当前流就是在最终的流。
但是,最终的流不一定是最大的,例如上面黄色的最终流总流量是9。我们还可以有总流量为12的流。
这个算法最核心,最巧妙的部分就在下面:
建立残存网络的时候,建立双向图,反向的边初始化容量都为0,其他不变。
当一条增广路径从残存网络中减掉的时候,每条边正向减去多少,就在反向边上加多少。
这时在更新后的残存网络中搜索新的增广路径,有可能用上反向路径。减去反向流量的时候会使之前已经消耗的正向流量增加,起到撤销之前路径的作用。流量往当前图叠加的时候,要注意方向,如果是反向的,要加负号也就是减去。
通过这种方式得到的最终流就是最大流。
至于为什么这样做是有效的,有数学严格证明是很复杂的。我们可以只观地看,无非就是验证三个问题:
添加不存在的路径为什么会通?
流量撤销之后,原来的路径为什么还通?
最终流量为什么是最大的?
用文字很难写出来,感兴趣的可以在B站搜这篇文章的同名视频。
有了上面的思路,有编程基础的就可以把程序写出来了,编程基础不好的可以找我学编程写程序。