最大流(MaxFlow)问题

给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow).

想象一条多条不同水流量的水管组成的网络, s为供水广, t为水用户, 最大流问题就是找到能够在s到t流通的最大水流量

一个流是最大流当且仅当其残存网络不包含任何增广路径(里面的名称在后面有详细解释)

流(Flow)的基本性质

设$C_{uv}$代表边u到v最大允许流量(Capacity), $f_{uv}$代表u到v的当前流量, 那么有一下两个性质:

$(u, v)$为有向图边, $0<=f_{uv}<=C_{uv}$, 即对于所有的边, 当前流量不允许超过其Capacity

除了$s, t$之外, 对所有节点有 $\sum\limits_{(v, u)}f_{wu} = \sum\limits_{(u, v)}f_{uv}$, 即对于任何一点, 流入该点的流量等于留出该点的流量, 流量守恒原则(类似与能量守恒的概念).

非负数值$f(u, v)$为从节点u到节点v的流.一个流$|f|$的定义: $$|f| = \sum\limits_{v \in V}f(s,v) - \sum\limits_{v \in V}f(v, s)$$

最大流问题即要找到一个最大的流f

Ford-Fulkerson方法

之所以称之为方法, 而不是算法, 因为FF(Ford-Fulkerson简称)包含不同运行时间的几种实现, 是一种迭代的方法.

该方法主要依赖于残存网络, 增广路径和割

//伪代码

初始化:所有流f = 0

while 在残存网络中存在增广路径p

增加流f的值

return f

残存网络

给定网络G和流量f, 残存网络$G_f$由那些仍有空间对流量进行调整的边构成.

残留网络 = 容量网络capacity - 流量网络flow

残存网络

增广路径

增广路径p是残存网络中一条从源节点s到汇点t的简单路径,在一条增广路径p上能够为每条边增加的流量的最大值为路径p的残存容量$c_f(p) = min \{c_f(u,v):(u,v) \in p \}$

在一条增广路径p上, 要增加整条增广路径的水流量, 则必须看最小能承受水流量的管道, 不然水管会爆掉, 这最小承受水流量就是残存容量

在有向图网络G中, 割(S, T)将V划分为S和T = V - S, 使得s属于S集合, t属于T集合. 割(S, T)的容量是指从集合S到集合T所有边的容量之和.

最大流

最大流最小割理论

设$f$为流网络G = (V, E)中的一个流, 该流网络的源节点为s, 汇点为t, 则下面的条件是等价的:

f是G的一个最大流

残存网络$G_f$不包含任何增广路径

$|f| = c(S, T)$, 其中(S, T)是流网络G的某个割

Ford-Fulkerson算法Java实现

伪代码

for each edge(u, v)属于G.E(图G的边)

(u, v).f = 0 //所有边的流为0

//循环终止条件为残存我昂罗中不存在增广路径

while s到t的残存网络中存在增广路径p:

c(p) = 最小残存容量

for 增广路径的每条边

if 这条边属于E集合

(u, v).f = (u, v).f + c(p) //意思是在原有的流增加最小残存容量.

else

(u, v).f = (u, v).f - c(p)

//边的定义

public class FlowEdge {

private final int v, w; //边的起点和终点

private final 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 capacity() {

return capacity;

}

public double flow() {

return flow;

}

public int other(int vertex) {

if (vertex == v) {

return w;

} else if (vertex == w) {

return v;

} else {

throw new RuntimeException("Inconsistent edge");

}

}

//v中残留流量

public double residualCapacityTo(int vertex) {

if (vertex == v) { //反向边

return flow;

} else if (vertex == w) { //正向边

return capacity - flow;

} else {

throw new IllegalArgumentException();

}

}

//向v中增加delta

public void addResidualFlowTo(int vertex, double delta) {

if (vertex == v) {

flow -= delta;

} else if (vertex == w) {

flow += delta;

} else {

throw new IllegalArgumentException();

}

}

}

//流图的定义

public class FlowNetwork {

private final int V; //顶点个数

private Bag[] adj;

public FlowNetwork(int V) {

this.V = V;

adj = (Bag[]) new Bag[V];

for (int v = 0; v < V; v++) {

adj[v] = new Bag<>();

}

}

//想流图中增加边

public void addEdge(FlowEdge e) {

int v = e.from();

int w = e.to();

adj[v].add(e); //正向边

adj[w].add(e); //反向边

}

public int V() {

return V;

}

public Iterable adj(int v) { //返回邻接边

return adj[v];

}

}

//FordFulkerson方法的实现

public class FordFulkerson {

private boolean[] marked; //如果残留网络中有s->v路径, 则为true

private FlowEdge[] edgeTo; //s->v路径的最后的边

private double value; //流

public FordFulkerson(FlowNetwork G, int s, int t) {

value = 0.0;

//当找不到增广路径时终止

while (hasAugmentingPaht(G, s, t)) { //判断是否还有增广路径

double bottle = Double.POSITIVE_INFINITY;

for (int v = t; v != s; v = edgeTo[v].other(v)) { //计算最大流量

bottle = Math.min(bottle, edgeTo[v].residualCapacityTo(v));

}

for (int v = t; v != s; v = edgeTo[v].other(v)) {

edgeTo[v].addResidualFlowTo(v, bottle);

}

value += bottle;

}

}

private boolean hasAugmentingPaht(FlowNetwork G, int s, int t) {

edgeTo = new FlowEdge[G.V()];

marked = new boolean[G.V()];

Queue q = new Queue<>();

q.enqueue(s);

marked[s] = true;

while (!q.isEmpty()) {

int v = q.dequeue();

for (FlowEdge e : G.adj(v)) {

int w = e.other(v);

if (e.residualCapacityTo(w) > 0 && !marked[w]) {

edgeTo[w] = e;

marked[w] = true;

q.enqueue(w);

}

}

}

return marked[t];

}

public double value() {

return value;

}

public boolean intCut(int v) { //在残留网络中v->s是否可达

return marked[v];

}

}

原文:http://www.cnblogs.com/maiyacheng/p/4495143.html

java 最大流最小割_最大流, 最小割问题及算法实现相关推荐

  1. 【图割】最大流/最小割算法详解(Yuri Boykov and Vladimir Kolmogorov,2004 )

    本博客主要翻译了Yuri Boykov and Vladimir Kolmogorov在2004年发表的改进最大流最小割算法用于计算机视觉的论文:An Experimental Comparison ...

  2. 最大流最小割经典例题_最大流, 最小割问题及算法实现

    本博客采用创作共用版权协议, 要求署名.非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议. 由于博文中包含一些LaTex格式数学公式, 在简书中显示不好, 所以 ...

  3. 网络流 最大流 最小割 费用流

    [腾讯文档]网络流初步 网络流初步 文章目录 网络流初步 一.网络流简介 1. 网络 2. 流 3. 再次理解网络流 二.常见题型(三种) 三.相关问题对应算法介绍 1.最大流 (1) FF算法 - ...

  4. 学习笔记:网络流基础:理解最大流/最小割定理 (蒋炎岩)

    网络流基础:理解最大流/最小割定理 蒋炎岩 课程链接 有向图的基本概念: 问题引入 直观感受反例 引入重要概念: 割的示例 小结 再来一个问题 例子 可以找到一条路径的情况 可以找到两条路径的情况 问 ...

  5. 【LuoguP33294123】[ZJOI2011]最小割[CQOI2016]不同的最小割

    链接1 链接2 题意简述 第一个题 : 问图中有多少不同的最小割数值 第二个题 : \(q\) 次询问图中多少对点对之间的最小割小于 \(x\) . Sol 两个都是模板题就放一起了. 求完最小割树直 ...

  6. P2774-方格取数问题【网络流,最大流,最小割】

    正题 链接: https://www.luogu.org/problemnew/show/P2774 题意 在一个n*m的数字矩阵中取数,取得数不能相邻,求能取到的最大价值. 解题思路 最大价值,那么 ...

  7. [ZJOI2009]狼和羊的故事【网络流】【最大流(最小割)】

    >Description 羊狼圈是一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆.在羊狼圈中再加入一些篱笆,将羊狼分开.狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非 ...

  8. Dinic求最大流/最小割

    o(v^2*E) 建图时建一条流量为0的反向边,正向边每减去流量f,反向边增加流量f.对于无向图当做两条边. cap:每条边最大流量 建图后: 调用DINIC():用bfs()为每个节点进行层次编号, ...

  9. Cops and Robbers(最大流 最小割)

    https://vjudge.net/problem/Kattis-copsandrobbers 题意: 将某些位置堵上,不能使得B出去,不同字母不同花费,求最小花费. 解析: 使B与外面分离,就是最 ...

  10. 最大流=最小割 简单证明

    割是什么 割的定义就是,在一个图中取出一些有向的边.把图一分为二,使得,再也没有办法,使得能从S到达T的流量. 我们有好多种,拿走边的方案,我们把拿走这些边的值加在一起,那么称作割的Value,现在记 ...

最新文章

  1. Collections.addAll() 的使用 以及和list.addAll() 的区别
  2. 计算机网络全部实验,计算机网络综合实验
  3. Solr及Spring-Data-Solr入门学习
  4. 《dp补卡——343. 整数拆分、96. 不同的二叉搜索树》
  5. [JavaScript] DOM操作技术
  6. oracle11g ora 12518,servlet执行update报错ORA-12518
  7. Oracle之自治事务
  8. python-元组数据类型
  9. c语言扩展运算符是什么,扩展运算符的6个重要用途
  10. 使用Presto SQL一些常见问题总结
  11. L3_01 01背包和最小序列
  12. java飞机大战微信版_微信飞机大战素材
  13. Linux V4L2驱动框架分析之(一):架构介绍
  14. 基于ros单线激光雷达的坐标读取
  15. C语言写程序注意,单片机C语言编程应注意的若干问题
  16. wifi-sdio接口
  17. MATLAB 图像识别
  18. 计算机表格折线图添加图例,如何将Excel表格中插入的折线图中的圆圈设置为方块或三角形...
  19. 人事系统中如何根据打卡数据自动产生考勤记录
  20. 计算机的基础配置,教你认知电脑基本配置

热门文章

  1. Android简易聊天室软件(HTTP实现)
  2. 程序员python开发简历范文_程序员简历就该这样写
  3. Beyond Compare 30天评估期结束解决办法
  4. 最小生成树——Prim算法(详细图解)
  5. 高考方向计算机基础试题题库,计算机基础考试题库 计算机基础考试题库(含答案).doc...
  6. Multisim14仿真基本模拟电路之 10.3.5有源滤波器电路的仿真实验与分析
  7. 蜘蛛采集单域名网站克隆镜像源码
  8. 基于用户 的协同过滤算法
  9. meshlab简单实践
  10. JS实现实时显示时间