算法9-5:最大流算法的Java代码
残留网络
在介绍最大流算法之前先介绍一下什么是残留网络。残余网络的概念有点类似于集合中的补集概念。
下图是残余网络的样例。
上面的网络是原始网络。以下的网络是计算出的残留网络。残留网络的作用就是用来描写叙述这个网络中还剩下多少能够利用的流量。
流量网络
最大流算法比曾经介绍的算法都要复杂。
网络中的每一条边须要记录容量和当前流量。容量是固定值,是已知条件,而当前流量在计算过程中会一直发生变化。因此,须要建立一个专门的类,用于最大流算法。
public class FlowEdge {
private int v;
private int w;
private double capacity;
private double flow;
public FlowEdge(int v, int w, double capacity) {
this.v = v;
this.w = w;
this.capacity = capacity;
}
public int from() {
return v;
}
public int to() {
return w;
}
public double capactity() {
return capacity;
}
public double flow() {
return flow;
}
public int other(int v) {
if (v == this.v) return this.w;
else return this.v;
}
// 返回可以添加的最大流量
public double residualCapacityTo(int v) {
if (v == this.v) return flow;
else return capacity - flow;
}
// 添加这条边的流量
public void addResidualFlowTo(int v, double d) {
if (v == this.v) flow -= d;
else flow += d;
}
}
与其它的图论算法类似,须要将图中全部的边替换成FlowEdge。于是得到了例如以下的类。
import java.util.LinkedList;
import java.util.List; public class FlowNetwork {
private int V;
private List<FlowEdge>[] adj; public FlowNetwork(int V) {
this.V = V;
adj = new LinkedList[V];
for (int i = 0; i < adj.length; i++) {
adj[i] = new LinkedList();
}
} public Iterable<FlowEdge> adj(int v) {
return adj[v];
} public int V() {
return V;
} public void addEdge(FlowEdge e) {
int v = e.from();
adj[v].add(e);
} @Override
public String toString() {
String result = "";
for (int i = 0; i < V; i++) {
result += i + ":";
for(FlowEdge e:adj[i]) {
result += " " + e.toString();
}
result += "\n";
}
return result;
}
}
算法类
依照惯例,须要为最大流算法编写一个专门的类。
该类的代码例如以下:
import java.util.LinkedList;
import java.util.Queue; public class FordFulkerson {
private FlowEdge[] edgeTo;
private double value; public FordFulkerson(FlowNetwork G, int s, int t) {
// 一直添加流量直到无法再添加为止
while (hasAugmentingPath(G, s, t)) {
// 找出增广路的瓶颈
double bottle = Double.POSITIVE_INFINITY;
int v = t;
while (v != s) {
bottle = Math.min(bottle, edgeTo[v].residualCapacityTo(v));
v = edgeTo[v].other(v);
} // 添加整条路径的流量
v = t;
while (v != s) {
edgeTo[v].addResidualFlowTo(v, bottle);
v = edgeTo[v].other(v);
} // 最大流添加
value += bottle;
}
} public double value() {
return value;
} // 推断是否有增广路
// 有增广路的条件就是存在一条路径,这条路径上全部的边都能添加流量。 private boolean hasAugmentingPath(FlowNetwork G, int s, int t) {
edgeTo = new FlowEdge[G.V()]; // 注意,这句话是必需要有的。由于每次增广路径都不一样。
boolean[] visited = new boolean[G.V()]; // BFS
Queue<Integer> q = new LinkedList<Integer>();
q.add(s);
visited[s] = true; // 注意:这句话不要遗漏
while (!q.isEmpty()) {
int v = q.poll(); // 可以通过的条件是流量可以添加
for (FlowEdge e : G.adj(v)) {
int w = e.other(v);
if (e.residualCapacityTo(w) > 0 && !visited[w]) {
edgeTo[w] = e;
q.add(w);
visited[w] = true;
}
}
} // 有增广路的条件就是S点可以到达T点。
return visited[t];
} public static void main(String[] argv) {
FlowNetwork g = new FlowNetwork(4);
int[] data = {0, 1, r(), 0, 2, r(), 2, 1, r(), 1, 3, r(), 2, 3, r(), 0, 3, r()};
for (int i = 0; i < data.length; i += 3) {
g.addEdge(new FlowEdge(data[i], data[i + 1], data[i + 2]));
}
StdOut.println(new FordFulkerson(g, 0, 3).value());
} private static int r() {
return StdRandom.uniform(1000);
}
}
算法9-5:最大流算法的Java代码的更多相关文章
- 排序算法对比,步骤,改进,java代码实现
前言 发现是时候总结一番算法,基本类型的增删改查的性能对比,集合的串并性能的特性,死记太傻了,所以还是写在代码里,NO BB,SHOW ME THE CODE! github地址:https://gi ...
- coding++:RateLimiter 限流算法之漏桶算法、令牌桶算法--简介
RateLimiter是Guava的concurrent包下的一个用于限制访问频率的类 <dependency> <groupId>com.google.guava</g ...
- 常用限流算法与Guava RateLimiter源码解析
在分布式系统中,应对高并发访问时,缓存.限流.降级是保护系统正常运行的常用方法.当请求量突发暴涨时,如果不加以限制访问,则可能导致整个系统崩溃,服务不可用.同时有一些业务场景,比如短信验证码,或者其它 ...
- 对一致性Hash算法,Java代码实现的深入研究
一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...
- Ford-Fulkerson 最大流算法
流网络(Flow Networks)指的是一个有向图 G = (V, E),其中每条边 (u, v) ∈ E 均有一非负容量 c(u, v) ≥ 0.如果 (u, v) ∉ E 则可以规定 c(u, ...
- 几种简单的负载均衡算法及其Java代码实现
什么是负载均衡 负载均衡,英文名称为Load Balance,指由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助.通过某种负载分担技 ...
- 一致性哈希算法学习及JAVA代码实现分析
1,对于待存储的海量数据,如何将它们分配到各个机器中去?---数据分片与路由 当数据量很大时,通过改善单机硬件资源的纵向扩充方式来存储数据变得越来越不适用,而通过增加机器数目来获得水平横向扩展的方式则 ...
- 大话数据结构(十二)java程序——KMP算法及改进的KMP算法实现
1.朴素的模式匹配算法 朴素的模式匹配算法:就是对主串的每个字符作为子串开头,与要连接的字符串进行匹配.对主串做大循环,每个字符开头做T的长度的小循环,直到成功匹配或全部遍历完成为止. 又称BF算法 ...
- 常见的排序算法之Java代码解释
一 简要介绍 一般排序均值的是将一个已经无序的序列数据重新排列成有序的 常见的排序分为: 1 插入类排序 主要就是对于一个已经有序的序列中,插入一个新的记录.它包括:直接插入排序,折半插入排序和希尔排 ...
随机推荐
- SGU 170.Particles
Solution: 这其实是道很简单的题. 只要从一端开始,以‘+’或‘-’,任意一种开始找,找到与目标串最近的相同字符的距离就是需要交换的次数 ...
- DBCONN
package Ulike_servlet; //将该类保存到com.tools包中import java.sql.Connection;import java.sql.DriverManager;i ...
- 关于javascript输出中文乱码的问题
今天找到一个引导效果.原来是用英文进行引导.但是我改了里面的英文为汉字就出现乱码的情况.英文提示是在js页面里面完成的.所以最后的解决办法 就是把js文件用记事本打开,然后把文件另存为utf-8的格式 ...
- Skinned Mesh原理解析和一个最简单的实现示例
Skinned Mesh 原理解析和一个最简单的实现示例 作者:n5 Email: happyfirecn##yahoo.com.cn Blog: http://blog.csdn.net/n5 ...
- 数组去重的三种方法及from方法
直接上代码: var str="adbbckddwerivka"; var arr=str.split(""); console.log(arr); //ind ...
- 如何为jquery添加方法
以下内容引自一位网友的帖子: jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery ...
- PHP框架_ThinkPHP基础
目录 1.ThinkPHP项目结构 2.ThinkPHP运行流程 3.ThinkPHP配置文件 4.ThinkPHP四种URL模式 5.ThinkPHP用户自定义函数 6.ThinkPHP模板展示及变 ...
- asp.net mvc 强类型视图中传入List 数据到控制器
问题来源: 在和一位技术老师聊天时,老师问我一个mvc 表单提交的问题,问道:怎样在表单提交的时候,将 带有 List 属性的对象传入控制器? 这时,我有点呆了,以前一直都好像是 单一属性的表单提交, ...
- 【译】UI设计基础(UI Design Basics)--导航(Navigation)(六)
[译]UI设计基础(UI Design Basics)--导航(Navigation)(六)
- 【转】SharePoint 2013 stand alone服务器安装
原文地址:http://www.cnblogs.com/jianyus/archive/2013/02/01/2889653.html 介绍:文章就是SharePoint2013安装过程的图解,包括 ...