如何证明Ford-Fulkerson网络流dijkstra算法过程图解的正确性

  最大流问题是网络优化中典型的问题用形象的语言来描述就是在满足容量约束的前提下将尽可能多的流从源节点(始点)到汇节点(终点)。解决此问题的经典方法很多夲文介绍广为人熟知的Ford-Fulkersondijkstra算法过程图解,来解决最大流问题尽管网上关于此问题的文章多如牛毛,但笔者希望结合自己学习过程中对dijkstra算法過程图解的理解给予dijkstra算法过程图解最清晰的介绍,希望对大家有帮助(笔者曾尝试使用java来实现,但最终因用java实现和使用图太麻烦了又鈈想重新用python来实现,故放弃以后的实现估计会采用python而不是java,java毕竟不适合写图相关dijkstra算法过程图解)

  学习此dijkstra算法过程图解前建议读者学習网络流相关知识和基本概念,一些需要了解的概念和知识先罗列如下

  2、最大流最小割定理

   (其中节点数为nbnm和cnm为边mn容量的最小囷最大值,xmn为边的流量 Tk+1集合的节点不能属于T其他集合节点)

  上式的含义即为Tk+1为在集合Tk中所有节点满足可增广路条件的相邻的节点组成嘚集合,当然这些节点不能包括已经存在其他T集合中的节点。

  当dijkstra算法过程图解终止时最后一个集合Tk有两种情况(假设s为起点, t为终點):

  (1) 最后一个集合Tk包含t此时从t向前标记即可构造从s到t的简单可增广路。即从T1,T2,T3,....,Tk中每个取一个节点的路

  (2)最后一个集合Tk为空集此时得箌一个分离s和t的饱和割集

  现举例说明,如下图(容量下限(最小值)流量,容量上限(最大值))标在每条边旁

  1为源点6为汇点。开始T0只有1個节点就是节点1。接下来从和T0中节点也就是节点1相邻的节点2和3开始。边12流量为0,为前向边满足流量小于容量上限;边13也为前向边,满足流量小于上限(0 < 1)所以节点2和节点3组成T1。然后考虑以节点2和节点3来寻找T2原理和前面一致,其中边35为后向边,流量为2大于容量下限1,所以节点5添加到T2。到最后T3集合包含6,终止此时增广路为(1,3,5,6)。

  现在看另一图只是把边56的流量改为了0,此时后向边56不满足流量夶于下限所以T3为空集。此时存在饱和割集{S, N-S}分离1和6其中S = {1,23,45},是所有集合Tk的并集

  在了解了可增广路搜索dijkstra算法过程图解后現在正式进入本文的主题,Ford-Fulkersondijkstra算法过程图解该dijkstra算法过程图解在每次迭代中改进原费用(s的散度),因此是原费用改进型dijkstra算法过程图解dijkstra算法过程图解思想是,给定可行流向量x(即满足容量可行且除了s和t之外节点的散度为零即节点流入和流出相等,的流向量)以及对于x可增广的从s箌t的路P,就可以增进P的前向边(i,j)的流量并减小P的后向边(i,j)的流量流量增量的最大值为  

  由此得到的流向量y由

  使用可增广路搜索dijkstra算法过程图解实现下述两种情况之一:

  (1)、得到将s和t分离的饱和割集

  (2)、得到从s到t的x的可增广路P。

  在情况1下dijkstra算法过程图解终止;此时的流向量即为所求。在情况2下沿着P进行增广,并进行下一次迭代每次增广时,dijkstra算法过程图解通过增广增量δ改进原费用(s的散度)現在以例子说明

对增广路中的所有边x12和x25使用δ改进费用,因为均为正向边,有新的流量为x12=0 + 1 = 1, x25= 0 + 1 = 1费用改进后如图3。费用改进后继续寻找增广蕗如图4。

在最后一次费用改进后已找不到增广路。其中T0包含节点1T1包含节点2,T3包含节点3因此饱和割集为[{1, 2, 3}, {4, 5}]。割集容量即为最大容量即5=c24 + c34 + c25  = 5

  在学习此dijkstra算法过程图解时,笔者已经尽力描述dijkstra算法过程图解的主要内容了由于需要有一些图论的知识作为辅助,加上dijkstra算法过程图解有些复杂所以结合文中例子效果会更好。

}

最大流问题常常出现在物流配送Φ可以规约为以下的图问题。最大流问题中图中两个顶点之间不能同时存在一对相反方向的边。

边上的数字为该条边的容量即在该條边上流过的量的上限值。最大流问题就是在满足容量限制条件下使从起点s到终点t的流量达到最大。在介绍解决最大流问题的Ford-Fulkerson方法之前先介绍一些基本概念。

根据图和各条边上的流可以画出一幅图的残存网络如下所示左图为流网络,右图为残存网络其中流网络中边仩的数字分别是流量和容量,如10/12那么10为边上的流量,12为边的容量残存网络中可能会存在一对相反方向的边,与流网络中相同的边代表嘚是流网络中该边的剩余容量在流网络中不存在的边代表的则是其在流网络中反向边的已有流量,这部分流量可以通过“回流”减少唎如,右图残存网络中边<s,v1>的剩余容量为4,其反向边<v1.s>的值为12即左图流网络中的边<s,v1>的流量。在残存网络中值为0的边不会画出,如边<v1,v2>

残存网络描述了图中各边的剩余容量以及可以通过“回流”删除的流量大小。在Ford-Fulkerson方法中正是通过在残存网络中寻找一条从s到t的增广路径,並对应这条路径上的各边对流网络中的各边的流进行修改如果路径上的一条边存在于流网络中,那么对该边的流增加否则对其反向边嘚流减少。增加或减少的值是确定的就是该增广路径上值最小的边。

Ford-Fulkerson方法的正确性依赖于这个定理:当残存网络中不存在一条从s到t的增廣路径那么该图已经达到最大流。这个定理的证明及一些与其等同的定理可以参考《dijkstra算法过程图解导论》

Ford-Fulkerson方法首先对图中的所有边的鋶量初始化为零值,然后开始进入循环:如果在残存网络中可以找到一条从s到t的增广路径那么要找到这条这条路径上值最小的边,然后根据该值来更新流网络

Ford-Fulkerson有很多种实现,主要不同点在于如何寻找增广路径最开始提出该方法的Ford和Fulkerson同学在其论文中都是使用广度优先搜索实现的,其时间复杂度为O(VE)整个dijkstra算法过程图解的时间复杂度为O(VE^2)。

下面我给出一个应用Bellman-Ford计算单源最短路径的dijkstra算法过程图解实现寻找一条增廣路径对于用邻接矩阵表示的图来说,该实现的时间复杂度为O(V^3)对于用邻接表表示的图来说,时间复杂度则为O(VE)

该实现应用了计算图的朂短路径方法中的思想,对图中的边反复在松弛操作从而计算得到一个源点到其它所有点的路径。这里我们不需要计算最短路径只要找到一条可行路径即可。上述findRoute方法的实现原理可以参考我前面的一篇文章

在寻找路径的同时,我们还要记录一个前驱子图priorMatrix其本质上是┅个一位数组,其记录了从顶点s到其它顶点的一条可行路径上的终点的前一个顶点于是我们就可以从前驱子图中找到从s到t的一条完整路徑。其正确性由图的最短路径的计算方法思想保证具体可以参考我另一篇博客

下面给出根据图和流网络计算残存网络的代码。

* @param c 二维矩阵记录每条边的容量 * @param f 输出流网络矩阵,二维矩阵记录每条边的流量

下面给出用于测试的代码。

上述代码构造的图如下所示

运行结果如丅,其中1为顶点s5为顶点t,2~5依次为顶点v1、v2、v3和v4

流网络和残存网络如下所示,其中左图为流网络右图为残存网络。

我们可以看到残存网絡中的确已经不存在一条从s到t的路径了此时Ford-Fulkerson方法的循环应该终止,最大流量为各边的流量相加之和即76。

完整的程序可以看到我的github项目

這个项目里面有本博客介绍过的和没有介绍的以及将要介绍的《dijkstra算法过程图解导论》中部分主要的数据结构和dijkstra算法过程图解的C实现有兴趣的可以fork或者star一下哦~ 由于本人还在研究《dijkstra算法过程图解导论》,所以这个项目还会持续更新哦~ 大家一起好好学习~
}

我要回帖

更多关于 dijkstra算法过程图解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信