最大流问题的Ford-Fulkerson解法_ford capacity 详解-程序员宅基地

技术标签: 算法  java  

这是一种方法,而不是算法,因为它包含具有不同运行时间的几种实现。该方法依赖于三种重要思想:残留网络,增广路径和割

我们先简单介绍下Ford-Fulkerson方法的基本思想。首先需要了解的是Ford-Fulkerson是一种迭代的方法。开始时,对所有的u,v属于V,f(u,v)=0(这里f(u,v)代表u到v的边当前流量),即初始状态时流的值为0。在每次迭代中,可以通过寻找一个“增广路径”来增加流值。增广路径可以看做是从源点s到汇点t之间的一条路径,沿该路径可以压入更多的流,从而增加流的值。反复进行这一过程,直到增广路径都被找出为止。

一、残留网络

顾名思义,残留网络是指给定网络和一个流,其对应还可以容纳的流组成的网络。具体说来,就是假定一个网络G=(V,E),其源点s,汇点t。设f为G中的一个流,对应顶点u到顶点v的流。在不超过C(u,v)的条件下(C代表边容量),从u到v之间可以压入的额外网络流量,就是边(u,v)的残余容量(residual capacity),定义如下:

r(u,v)=c(u,v)-f(u,v)

举个例子,假设(u,v)当前流量为3/4,那么就是说c(u,v)=4,f(u,v)=3,那么r(u,v)=1。

我们知道,在网络流中还有这么一条规律。从u到v已经有了3个单位流量,那么从反方向上看,也就是从v到u就有了3个单位的残留网络,这时r(v,u)=3。可以这样理解,从u到v有3个单位流量,那么从v到u就有了将这3个单位流量的压回去的能力。

我们来具体看一个例子,如下图所示一个流网络


其对应的残留网络为:


二、增广路径

在了解了残留网络后,我们来介绍增广路径。已知一个流网络G和流f,增广路径p是其残留网络Gf中从s到t的一条简单路径。形象的理解为从s到t存在一条不违反边容量的路径,向这条路径压入流量,可以增加整个网络的流值。上面的残留网络中,存在这样一条增广路径:


其可以压入4个单位的流量,压入后,我们得到一个新的流网络,其流量比原来的流网络要多4。这时我们继续在新的流网络上用同样的方法寻找增广路径,直到找不到为止。这时我们就得到了一个最大的网络流。

三、流网络的割

上面仅仅是介绍了方法,可是怎么证明当无法再寻找到增广路径时,就证明当前网络是最大流网络呢?这就需要用到最大流最小割定理。

首先介绍下,割的概念。流网络G(V,E)的割(S,T)将V划分为S和T=V-S两部分,使得s属于S,t属于T。割(S,T)的容量是指从集合S到集合T的所有边(有方向)的容量之和(不算反方向的,必须是S-àT)。如果f是一个流,则穿过割(S,T)的净流量被定义为f(S,T)(包括反向的,SàT的为正值,T—>S的负值)。将上面举的例子继续拿来,随便画一个割,如下图所示:


割的容量就是c(u,w)+c(v,x)=26

当前流网络的穿过割的净流量为f(u,w)+f(v,x)-f(w,v)=12+11-4=19

显然,我们有对任意一个割,穿过该割的净流量上界就是该割的容量,即不可能超过割的容量。所以网络的最大流必然无法超过网络的最小割。

可是,这跟残留网络上的增广路径有什么关系呢?

首先,我们必须了解一个特性,根据上一篇文章中讲到的最大流问题的线性规划表示时,提到,流网络的流量守恒的原则,根据这个原则我们可以知道,对网络的任意割,其净流量的都是相等的。具体证明是不难的,可以通过下图形象的理解下,

 


和上面的割相比,集合S中少了u和v,从源点s到集合T的净流量都流向了u和v,而在上一个割图中,集合S到集合T的流量是等于u和v到集合T的净流量的。其中w也有流流向了u和v,而这部分流无法流向源点s,因为没有路径,所以最后这部分流量加上s到u和v的流量,在u和v之间无论如何互相传递流,最终都要流向集合T,所以这个流量值是等于s流向u和v的值的。将s比喻成一个水龙头,u和v流向别处的水流,都是来自s的,其自身不可能创造水流。所以任意割的净流量都是相等的。

万事俱备,现在来证明当残留网络Gf中不包含增广路径时,f是G的最大流。

假设Gf中不包含增广路径,即Gf不包含从s到v的路径,定义S={v:Gf中从s到v存在一条通路},也就是Gf中s能够有通路到达的点的集合,显然这个集合不包括t,因为s到t没有通路。这时,我们令T=V-S。那么(S,T)就是一个割。如下图所示:


那么,对于顶点u属于S,v属于T,有f(u,v)=c(u,v)。否则(u,v)就存在残余流量,因而s到u加上u到v就构成了一条s到v的通路,所以v就必须属于S,矛盾。因此这时就表明当前流f是等于当前的割的容量的,因此f就是最大流。(以上的概念都是转载他人的http://blog.csdn.net/smartxxyx/article/details/9293665)

以下是代码实现(java版)

package com.maxStream;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class MaxFlow1 {
    
  private int num=6;
  private int[] path=new int[6];//path[i]当前节点i节点的路径path[i]
 
 /**
  * @param graph
  * @param s 开始节点
  * @param t 结束节点
  * @return  判断有没有从起点到终点的路径
  */
 private boolean hasPath(int[][] graph,int s,int t){
     boolean[] visited=new boolean[num];
     Arrays.fill(visited, false);
     Queue<Integer> queue=new LinkedList<Integer>();
     queue.add(s);
     visited[s]=true;
     while(queue.size()>0){
         int top=queue.poll();
         for(int i=0;i<num;i++){
             if(graph[top][i]>0&&visited[i]==false){
                 queue.add(i);
                 visited[i]=true;
                 path[i]=top;//给路径数组赋值
             }
         }
     }
     return visited[t]==true;
 }
 
 /**
  * @param graph  有向图矩阵
  * @param s  源点
  * @param t  终点
  * @return   最大流
  */
 private int maxFlow(int[][] graph,int s,int t){
     int[][] rGraph=new int[num][num];
     for(int i=0;i<num;i++)
         for(int j=0;j<num;j++)
             rGraph[i][j]=graph[i][j];
    
     int maxFlow=0;
     while(hasPath(rGraph, s, t)){
         int min=Integer.MAX_VALUE;
         //找到当前路径中最小的权值
         for(int v=t;v!=s;v=path[v]){
             int u=path[v];
             if(rGraph[u][v]<min)
                 min=rGraph[u][v];
         }
         System.out.print("min-->"+min);
        
         //当前路径减去最小权值
         for(int v=t;v!=s;v=path[v]){
             int u=path[v];
             System.out.print("<--"+u);
             rGraph[u][v]-=min;
             rGraph[v][u]+=min;
         }
         System.out.println();
         maxFlow+=min;
        
     }
     return maxFlow;
 }
 public static void main(String[] args) {
     int graph[][] = { { 0, 16, 13, 0, 0, 0 },
              { 0, 0, 10, 12, 0, 0 },
              { 0, 4, 0, 0, 14, 0 },
              { 0, 0, 9, 0, 0, 20 },
              { 0, 0, 0, 7, 0, 4 },
              { 0, 0, 0, 0, 0, 0 } };
     int s=0;
     int t=5;
    int sum=new MaxFlow1().maxFlow(graph, s, t);
    System.out.println(sum);
}

}



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qingmuluoyang/article/details/72307171

智能推荐

ECharts--中国地图(无敌详细)_echarts中国地图-程序员宅基地

文章浏览阅读5.4w次,点赞64次,收藏262次。使用Echarts绘制中国地图,其中地图点信息由JSON文件编写,前端html直接从JSON文件中读取地区数据,渲染到前端即可。详细介绍用到的各个功能!代码直接复制运行即可!_echarts中国地图

数据类型转换问题-程序员宅基地

文章浏览阅读343次,点赞9次,收藏10次。使用函数tolist()之后数据发生变化,从小数点后4位变成小数点后16位,如何才能让数据不变化?list:包含3608个[128,100]的张量。使用for循环将张量都转化成二维数组列表。

element中表单错误提示信息被遮盖_el-form-item_error文字过长-程序员宅基地

文章浏览阅读5.9k次。提示信息被遮盖解决方法  可以给form-item加一个特定的class,不影响其他的提示框,然后设定width,可以把所有内容显示。代码vue的template代码<el-form-item label="用户微信" prop="userWeChat" class="weixinError"> <el-input v-model="userInfo.userWeChat" maxlength="20"></el_el-form-item_error文字过长

sqlmap安装以及运用_kali安装sqlmap-程序员宅基地

文章浏览阅读1.7k次。sqlmap是一个开源的渗透测试工具,它可以自动化检测sql注入漏洞利用sql注入缺陷 接管数据库服务器。_kali安装sqlmap

【曼哈顿距离】第六届蓝桥杯省赛C++ B组 /JAVA A组C组《移动距离》(c++)_移动距离 蓝桥杯 c++-程序员宅基地

文章浏览阅读598次,点赞19次,收藏4次。本题来自第六届蓝桥杯省赛C++ B组 /JAVA A组C组《移动距离》_移动距离 蓝桥杯 c++

zram disksize 设置_use_dedup-程序员宅基地

文章浏览阅读3.4k次。zram disksize 设置小内存项目:1G,2G,3G RAMzram disksize设置.高通:高通的设置比较简单:相关代码:init.qcom.post_boot.shif [ -f /sys/block/zram0/disksize ]; thenif [ -f /sys/block/zram0/use_dedup ]; thenecho 1 > /sys/block/zram0/use_dedupfiif [ $MemTotal -le5242_use_dedup

随便推点

mysql异常代码c0000005_win7系统因0xc0000005错误导致应用程序无法正常启动的解决方法...-程序员宅基地

文章浏览阅读2k次。很多小伙伴都遇到过win7系统因0xc0000005错误导致应用程序无法正常启动的困惑吧,一些朋友看过网上零散的win7系统因0xc0000005错误导致应用程序无法正常启动的处理方法,并没有完完全全明白win7系统因0xc0000005错误导致应用程序无法正常启动是如何解决的,今天小编准备了简单的解决办法,只需要按照1、右键点击要运行的软件或游戏,在右键菜单中选择“兼容性疑难解答”; 2、让系..._mysql 0xc0000005

UNIX环境高级编程_标准io创建空头文件-程序员宅基地

文章浏览阅读492次。unix环境高级编程笔记_标准io创建空头文件

apt-get update 报错:*** Error in `appstreamcli‘: double free or corruption (fasttop)_sudo apt-get update error in appstreamcli-程序员宅基地

文章浏览阅读1.3k次。环境:ubuntu 16.04在执行apt-get update时直接报错了,错误信息如下:从返回的错误信息可以看出,问题出在“appstreamcli”上。通过以下命令可以解决:sudo apt install appstream/xenial-backportssudo appstreamcli refresh –force亲测可行。..._sudo apt-get update error in appstreamcli

matlab文件路径操作 mfilename_matlab里面打开文件找不到main-程序员宅基地

文章浏览阅读9.5k次,点赞3次,收藏20次。很多时候我们需要把代码发给别人,而运行的代码可能包含路径。例如,你在你的电脑上需要加载一个mat文件,你的代码中包含了这个mat文件的具体的路径。例如,load('C:\Users\ncf\Desktop\计算机视觉大作业\program\xixi.mat'),当你把这个代码文件夹压缩发给别人时,别人一运行就会报错,这时我们需要自动识别,mat文件的路径。mfilename函数可以返回当前..._matlab里面打开文件找不到main

ssm+jsp计算机毕业设计职业高中学情成绩系统ci2a1(程序+lw+源码+远程部署)-程序员宅基地

文章浏览阅读22次。Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。2. 前端:L ayui+css+javascript+jQuery+ElemenUI+highcharts。SSM + mybatis + Maven + JSP 等等组成,B/S模式 + Maven管理等等。2. 使用IDEA/Eclipse/MyEclipse导入项目,修改配置,运行项目;

Windows命令行(CMD/Powershell)下载文件的命令_windows 命令提示符下载网页文件命令-程序员宅基地

文章浏览阅读733次,点赞3次,收藏8次。Windows命令行下载文件的方法_windows 命令提示符下载网页文件命令