图的匹配问题与最大流问题(三)——最大流问题Ford-Fulkerson方法Java实现
上篇文章主要介绍了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实现的更多相关文章
- Java进阶(三十六)深入理解Java的接口和抽象类
Java进阶(三十六)深入理解Java的接口和抽象类 前言 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太 ...
- vlookup函数基本使用--如何将两个Excel表中的数据匹配;excel表中vlookup函数使用方法将一表引到另一表
vlookup函数基本使用--如何将两个Excel表中的数据匹配:excel表中vlookup函数使用方法将一表引到另一表 一.将几个学生的籍贯匹配出来‘ 二.使用查找与引用函数 vlookup 三. ...
- tomcat启动(三)Catalina分析-load方法分析
load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...
- 同源策略(same-origin policy)及三种跨域方法
同源策略(same-origin policy)及三种跨域方法 1.同源策略 含义: 同源是指文档的来源相同,主要包括三个方面 协议 主机 载入文档的URL端口 所以同源策略就是指脚本只能读取和所属文 ...
- 深入理解javascript函数系列第三篇——属性和方法
× 目录 [1]属性 [2]方法 前面的话 函数是javascript中的特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本 ...
- .Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) 通过MVC控制器导出导入Excel文件(可用于java SSH架构)
.Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) [原文地址] 通过MVC控制器导出导入Excel文件(可用于java SSH架构) public cl ...
- Windows 8关机的三个最简单方法
Win8怎么关机?全新的Win8系统给用户一个难题,Win8如何关机?笔者整理了Win8关机的最实用的三个方法,希望能让大家了解Win8关机的具体操作,解决Win8如何关机等问题. 最常规的Win8关 ...
- CSS两列及三列自适应布局方法整理
布局 自适应 两列 三列 在传统方法的基础上加入了Flex布局并阐述各方法的优缺点,希望对大家有所帮助.先上目录: 两列布局:左侧定宽,右侧自适应 方法一:利用float和负外边距 方法二:利用外边距 ...
- JSON三种数据解析方法(转)
原 JSON三种数据解析方法 2018年01月15日 13:05:01 zhoujiang2012 阅读数:7896 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- vue mandmobile ui实现三列列表的方法
vue mandmobile ui实现三列列表的方法 请问这种列表的要用那个组件好呢?Cellitem 只能用到两列,这个要三列的怎么弄?mand的好像没有listview,grid组件的 问了man ...
随机推荐
- jmeter之GUI运行原理
一.一语道破jmeter 大家都知道我们在应用jmeter的图形化界面来进行操作,保存后生成的是一个.jmx文件. 那么这个.jmx文件中都是些什么呢. <?xml ve ...
- CORS(跨域资源共享)跨域问题及解决
当使用ajax跨域请求时,浏览器报错:XmlHttpRequest error: Origin null is not allowed by Access-Control-Allow-Origin.肯 ...
- 让低版本的IE浏览器 强制渲染为IE8 或者 以上 浏览器模式
让低版本的IE浏览器 强制渲染为IE8 或者 以上 浏览器模式 那么就要用下面的方法:让网页兼容ie9 复制代码 代码如下: <!–[if lte IE 8]> <meta http ...
- selenium2入门 定位 窗体切换等等 (二)
定位用的html素材有两个 demo.html <html> <head> <title>UI Automation Testing</title> & ...
- 使用STM32CubeMX来创建属于自己的工程
使用STM32CubeMX的好处就是GPIO口可以使用图形化的方式进行配置,配置完成之后可以立即生成支持多种编译器的工程文件,之后打开即可编译通过了,非常方便. 操作很简单,如下所述: 1 从ST的官 ...
- Asterisk 未来之路3.0_0004
原文:Asterisk 未来之路3.0_0004 Asterisk Wiki asterisk 的Wiki是很多启迪和困惑的发源地,另外一个最重要的VOIP知识库www.voip-info.org ...
- leetcode 34 Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the ...
- solr的安装与配置
solr的安装与配置 不久之前开发了一个项目,需要用到solr,因为所以在开始再网上查找资料,但是发现大部分的资料都是很片面的,要么就是只讲解solr如何安装的,要么就是只讲解solr的某一个部分的, ...
- Visual Studio 2014
开发 ASP.NET vNext 初步总结(使用Visual Studio 2014 CTP1) 2014-06-06 18:04 by 梁逸晨, 2149 阅读, 29 评论, 收藏, 编辑 新特性 ...
- 迷你 MVC
深入研究 蒋金楠(Artech)老师的 MiniMvc(迷你 MVC),看看 MVC 内部到底是如何运行的 2014-04-05 13:52 by 自由的生活, 645 阅读, 2 评论, 收藏, 编 ...