上篇文章主要介绍了Ford-Fulkerson方法的理论基础,本篇给出一种Java的实现。

先借助伪代码熟悉下流程

FORD-FULKERSON(G,t,s)

1 for each edge(u,v)属于E(G)

2     do f[u,v]=0

3          f[v,u]=0

4 while there exists a path p from s to t in the residual network Gf

5       do cf(p)=min{cf(u,v):(u,v)is in p}

6        for each edge (u,v) in p

7              do f[u,v]=f[u,v]+cf(p)

8                    f[v,u]=-f[u,v]

如果在4行中用广度优先搜索来实现对增广路径p的计算,即找到s到t的最短增广路径,能够改进FORD-FULERSON的界,这就是Ford-Fulkerson方法的Edmonds-Karp算法

证明该算法的运行时间为O(VE*E),易知,对流增加的全部次数上界为O(VE),每次迭代时间O(E)

package maxflow;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue; import util.EdgeUtil;
import util.NodeUtil;
import entry.Edge;
import entry.Node;
/**
* Ford Fulkerson方法求最大流,这是一种迭代的方法,开始是,初始流为0,每次迭代中,课通过寻找一条增广路径来增加流值。反复进行这一过程,直至找不到任何增广路径
* 本算法使用了Edmonds-Karp算法(一种对Ford Fulkerson方法的实现),在寻找增广路径时使用了寻找s到t的最短路径的方法。复杂度O(VE2)
* @author xhw
*
*/
public class FordFulkerson { private static double residualNetwork[][]=null;
private static double flowNetwork[][]=null; /**
* @param args
*/
public static void main(String[] args) {
double 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}}; System.out.println(edmondsKarpMaxFlow(graph,0,5)); }
/**
* 实现FordFulkerson方法的一种算法——edmondsKarp算法
* @param graph
* @param s
* @param t
* @return
*/
public static double edmondsKarpMaxFlow(double graph[][],int s,int t)
{
int length=graph.length;
//List<Node> nodeList=NodeUtil.generateNodeList(graph);
double f[][]=new double[length][length];
for(int i=0;i<length;i++)
{
for(int j=0;j<length;j++)
{
f[i][j]=0;
}
}
double r[][]=residualNetwork(graph,f); Node result=augmentPath(r,s,t);
double sum=0;
while(result!=null)
{
double cfp=0;
cfp=minimumAugment(r,result);
//说明已经没有增广路径了
if(cfp==0)
{
break;
} while(result.getParent()!=null)
{
Node parent=result.getParent(); f[parent.nodeId][result.nodeId]+=cfp;
f[result.nodeId][parent.nodeId]=-f[parent.nodeId][result.nodeId]; result=parent;
} sum+=cfp;
r=residualNetwork(graph,f);
result=augmentPath(r,s,t); } residualNetwork=r;
flowNetwork=calculateFlowNetwork(graph,r); /*for(int i=0;i<length;i++)
{
for(int j=0;j<length;j++)
{ System.out.print((flowNetwork[i][j]>0?flowNetwork[i][j]:0.0)+" ");
}
System.out.println();
}*/
return sum;
}
/**
* 计算最终的流网络,也就是最大流网络
* @param graph
* @param r
* @return
*/
private static double[][] calculateFlowNetwork(double[][] graph, double[][] r) {
int length=graph.length;
double f[][]=new double[graph.length][graph.length];
for(int i=0;i<length;i++)
{
for(int j=0;j<length;j++)
{
f[i][j]=graph[i][j]-r[i][j];
}
}
return f;
} /**
* 确定增广路径可扩充的流值
* @param graph
* @param result
* @return
*/
public static double minimumAugment(double graph[][],Node result)
{
double cfp=Double.MAX_VALUE;
while(result.getParent()!=null)
{
Node parent=result.getParent(); double weight=graph[parent.nodeId][result.nodeId];
if(weight<cfp&&weight>0)
{
cfp=weight;
}
else if(weight<=0)
{
cfp=0;
break;
}
result=parent;
}
return cfp;
} /**
* 计算残余网络
* @param c
* @param f
* @return
*/
private static double[][] residualNetwork(double c[][],double f[][]) {
int length=c.length;
double r[][]=new double[length][length];
for(int i=0;i<length;i++)
{
for(int j=0;j<length;j++)
{
r[i][j]=c[i][j]-f[i][j];
}
} return r;
} /**
* 广度优先遍历,寻找增光路径,也是最短增广路径
* @param graph
* @param s
* @param t
* @return
*/
public static Node augmentPath(double graph[][],int s,int t)
{
Node result=null;
List<Node> nodeList=NodeUtil.generateNodeList(graph);
nodeList.get(s).distance=0;
nodeList.get(s).state=1; Queue<Node> queue=new LinkedList<Node>();
queue.add(nodeList.get(s)); while(!queue.isEmpty())
{
Node u=queue.poll();
for(Node n:u.getAdjacentNodes())
{
if(n.state==0)
{
n.state=1;
n.distance=u.distance+1;
n.setParent(u);
queue.add(n);
}
}
u.state=2;
if(u.nodeId==t)
{
result=u;
break;
}
}
return result; } public static double[][] getResidualNetwork() { return residualNetwork; } public static double[][] getFlowNetwork() {
return flowNetwork;
} }

图的匹配问题与最大流问题(三)——最大流问题Ford-Fulkerson方法Java实现的更多相关文章

  1. Java进阶(三十六)深入理解Java的接口和抽象类

    Java进阶(三十六)深入理解Java的接口和抽象类 前言 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太 ...

  2. vlookup函数基本使用--如何将两个Excel表中的数据匹配;excel表中vlookup函数使用方法将一表引到另一表

    vlookup函数基本使用--如何将两个Excel表中的数据匹配:excel表中vlookup函数使用方法将一表引到另一表 一.将几个学生的籍贯匹配出来‘ 二.使用查找与引用函数 vlookup 三. ...

  3. tomcat启动(三)Catalina分析-load方法分析

    load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...

  4. 同源策略(same-origin policy)及三种跨域方法

    同源策略(same-origin policy)及三种跨域方法 1.同源策略 含义: 同源是指文档的来源相同,主要包括三个方面 协议 主机 载入文档的URL端口 所以同源策略就是指脚本只能读取和所属文 ...

  5. 深入理解javascript函数系列第三篇——属性和方法

    × 目录 [1]属性 [2]方法 前面的话 函数是javascript中的特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本 ...

  6. .Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) 通过MVC控制器导出导入Excel文件(可用于java SSH架构)

    .Net MVC  导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) [原文地址] 通过MVC控制器导出导入Excel文件(可用于java SSH架构)   public cl ...

  7. Windows 8关机的三个最简单方法

    Win8怎么关机?全新的Win8系统给用户一个难题,Win8如何关机?笔者整理了Win8关机的最实用的三个方法,希望能让大家了解Win8关机的具体操作,解决Win8如何关机等问题. 最常规的Win8关 ...

  8. CSS两列及三列自适应布局方法整理

    布局 自适应 两列 三列 在传统方法的基础上加入了Flex布局并阐述各方法的优缺点,希望对大家有所帮助.先上目录: 两列布局:左侧定宽,右侧自适应 方法一:利用float和负外边距 方法二:利用外边距 ...

  9. JSON三种数据解析方法(转)

    原 JSON三种数据解析方法 2018年01月15日 13:05:01 zhoujiang2012 阅读数:7896    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...

  10. vue mandmobile ui实现三列列表的方法

    vue mandmobile ui实现三列列表的方法 请问这种列表的要用那个组件好呢?Cellitem 只能用到两列,这个要三列的怎么弄?mand的好像没有listview,grid组件的 问了man ...

随机推荐

  1. CSS代码实现图片防盗链

    CSS代码实现图片防盗链的方法其实很简单.在CSS文件中添加以下代码: img { filter:exPRession( this.不能去掉 ? "" : ( (!this.com ...

  2. PHP 以POST方式提交XML、获取XML,最后解析XML

    以POST方式提交XML // Do a POST $data="<?xml version='1.0' encoding='UTF-8'?> <TypeRsp> & ...

  3. Python 2.7.3 Time与DateTime格式化

    import time import datetime class TimeX: '''时间工具,目前用于格式化时间''' @staticmethod def GetLocalTimeString_T ...

  4. C/C++软件静态测试现状

    对于C/C++软件而言,静态测试越来越趋向软件安全功能测试.包括数据机密性.完整性.可用性.不可否认性.身份认证.授权.访问控制.审计跟踪.委托.隐私保护.安全管理等. 通常情况下,C/C++静态测试 ...

  5. Asp.Net MVC页面静态化功能实现一:利用IHttpModule和ResultFilter

    由于公司现在所采用的是一套CMS内容管理系统的框架,所以最近项目中有一个需求提到要求实现页面静态化的功能.在网上查询了一些资料和文献,最后采用的是小尾鱼的池塘提供的 利用ResultFilter实现a ...

  6. 使用Flexible实现手淘H5页面的终端适配(转)

    曾几何时为了兼容IE低版本浏览器而头痛,以为到Mobile时代可以跟这些麻烦说拜拜.可没想到到了移动时代,为了处理各终端的适配而乱了手脚.对于混迹各社区的偶,时常发现大家拿手机淘宝的H5页面做讨论—— ...

  7. 用批处理文件自动备份文件及文件夹,并自动删除n天前的文件

    原文:用批处理文件自动备份文件及文件夹,并自动删除n天前的文件 ---恢复内容开始--- 下是备份的批处理,添加到"计划任务"中,设定时间自动运行 复制代码 代码如下:@echo ...

  8. 如何用dumpbin.exe检查编译器生成的托管模块所嵌入的信息

    开启CMD 运行到dumpbin目录下:D:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin 运行命令VCVARS32.BAT,配置环境 ...

  9. CSS绘制无图片的气泡对话框

    <div class="qipao_contianer">            <div class="qipao_content yj3" ...

  10. 开发使用混合式Winform模块

    开发使用混合式Winform模块 1.Winform数据访问模式定义 传统的Winform程序模块:用于传统的数据库通讯获取数据,这种方式获取数据,方便快捷,可以用于常规的业务系统的场景,用于单机版软 ...