前言
在介绍如何使用dijkstra算法求解最小费用最大流问题的时候,假设看这篇博文的读者已经知道什么是最小费用最大流问题及熟悉dijkstra单源最短路径算法。在这篇博文里面,我并不会过多强调网络拓扑是有向图和无向图,因为对于无向图来说,你可以简单将其看成两个点之间有一对有向边的有向图。
经典求法
求解最大最小费用最大流经常有两种方式:
1. 每次求出一条费用最小费用的增广路径 p ,将其加到当前费用流 f ,得到更新后的费用流 f′ ,直到找不到增广路径为止
2. 先求网络的最大流 fmax ,然后不停的遍历图移动费用流 fmax 的路径,使其费用降低,直到其费用不能降低为止。
使用dijkstra算法求解最小费用最大流网络使用的是第一种方式,对于第一种方式,网上的博客关于如何选择最小费用的增广路径的方式一般都是给出的SPFA(shortest path fast algorithm)方法。选择该方式有一定原因是在求最小费用最大流问题的时候,其反向边的权值是负权值,而该算法是基于经典的Bellman Ford算法优化的一种高效的可以用于求解负权值的算法。但是,其实这种方式就效率来说远远不及dijkstra算法,但为什么网上的博客中在介绍最小费用最大流算法的时候没有人介绍使用dijkstra算法了?因为dijkstra算法不能用于求解具有负权值的网络,所以他们觉得在这里dijkstra算法不适合。但是其实可以通过dijkstra算法去求解最小费用最大流网络。下面就来给出相关解释。
定义
为了说明算法的合理性,先给出一下定义:
对于两个点 u , v ,存在一个流 f 从u经过v,不失一般性,我们将
f(u,v) 方向的边定义为正向边,将 f(v,u) 方向的边定义为反向边,通常如果将正向边的权值定义为 C(u,v)=c ,反向边的权值将是 C(v,u)=−c 。
合理性证明
能够使用dijkstra算法的前提基于以下几个前提
1.在最小费用最大流中,任何结点对 (u,v) ,始终只存在一个方向的流 f ,该方向要不是从 u 到 v ,要不是 v 到 u 。
2.在使用第一条方式求解最小费最大流算法时候,每次选择最小费用增广路径一定是当前残留图的最小增广路径。
3. 由于网络拓扑的费用和容量都是正值,而其反向边的存在是存在一定限制的,所以在网络中永远不可能有负环的存在。
让我先来说说第一点,如果一个结点对之间存在两个方向的流(对于无向图或有一对有向边的有向图),那么其一定不是最小费用最大流网络,因为在该结点对上的两个方向流是可以互相抵消的,肯定会存在一个两个方向互相抵消的更小费用的最大流网络。
第二点,我们在使用第一种方式的时候,每次选择的路径都必须是最小费用增广矩阵,这样才能保证我们最后得到的最小费用最大流网络
第三点,因为网络拓扑给的容量和费用都是正值,而只有当一条边有流量通过之后,才存在其反向边的概念,而其反向边的最用就是为了回流,其容量限制就是正向边的通过的流量,所以网络拓扑中不可能存在负环。
而dijkstra算法不能应用负权值网络是因为其使用的是贪心策略,所以导致对于有负权值的边有可能不会遍历。但是注意我们所说到的前提第二点和第三点。负权值反向边出现的条件是在正向边有流量通过,且我们每次选择最小费用的增广路径。而正因为两个限制弥补了dijkstra算法贪心策略的不足。大家自己画画图就可以理解了,所以这里我就不画图说明。
因此,正因为以上两条限制,所以完全可以使用dijkstra替换spfa来寻找最小费用最大流网络。