网络流(3)——找到最小st-剪切
在大规模战争中,后勤补给是重中之重,为了尽最大可能满足前线的物资消耗,后勤部队必然要充分利用每条运输网。与此同时,交战双方也想要以最小的代价切断敌军的补给,从而使敌军处于孤立无援的境地。在古今中外的各种重大战役中,上演了一幕幕补给线上的攻防战。
甲军的运输路线
假设甲、乙两军正在交战,图8.17是甲军的补给运输网,其中t是甲军的前沿阵地,s是后勤大营,每条边是一条公路,边上的数字代表公路的宽度。

如果甲军想要尽最大努力供应前线的消耗,应该怎样设计运输路线?
这个问题很容易规约成网络流模型,使用下面的代码可以直接计算出结果。
import network_flow as nf V = [0, 1, 2, 3, 4, 5, 6, 7, 8]
E = [nf.Edge(0, 1, 15), nf.Edge(0, 2, 15), nf.Edge(0, 3, 15), nf.Edge(1, 4, 2), nf.Edge(2, 4, 3),
nf.Edge(2, 5, 2), nf.Edge(3, 5, 4), nf.Edge(4, 5, 2), nf.Edge(4, 6, 2), nf.Edge(5, 6, 4),
nf.Edge(5, 7, 3), nf.Edge(6, 8, 15), nf.Edge(7, 8, 15)]
s, t = 0, 8
G = nf.Network(V, E, s, t)
ford_fullkerson = nf.FordFulkerson(G)
ford_fullkerson.start()
ford_fullkerson.display()
X, Y, st_cut = ford_fullkerson.min_st_cut()
ford_fullkerson.display_st_cut(X, Y, st_cut)
(network_flow参考上一章的相关代码)运行结果对应的网络流:

乙军的轰炸目标
甲军想要充分利用每条公路,乙军的目的正好相反,是破坏公路网,使乙军的战斗部队处于孤立无援的境地。乙军打算组织一次针对甲军补给线的战略轰炸,由于甲军在每个节点都部署了大量防空武器,因此需要绕过节点,直接轰炸防御薄弱的公路。假设炸掉容量为1的公路需要n颗炸弹,破坏的公路容量和投掷的炸弹数成正比,怎样设计轰炸目标才能以最小的代价完全破坏敌军的补给线?
一个方案是炸毁直接通向汇点的公路,但由于连接汇点的两条公路太宽,完全破坏需要30n的炸弹,这显然不是最小代价。如果换个地点,假设轰炸的是v5→v7,那么只需要3n的炸弹就可以使宽敞的v7→t沦为摆设。为了设计这种轰炸方案,需要理解最小st-剪切的概念。
8.3.3 最小st-剪切
设计成本最低的轰炸方案是我们的目标,直接寻找起来比较困难,幸而这个目标与网络的最小剪切有密切关系。
一个流网络的顶点可以划分成两个不相交的集合X和Y,源点s和汇点t分属于这两个集合,连接X和Y的边称为这个流网络的st-剪切(st-cut,也称为截、割或切割)。我们用浅色圆圈表示包含源点的集合X,深色圆圈表示包含汇点的集合Y,这样就很容易看出一个流网络的st-剪切:

既然st-剪切是边的集合,那么集合中边的容量之和就是st-剪切的容量。一个流网络有很多种不同的st-剪切,其中容量最小的一个就是最小st-剪切。
st-剪切包含了所有源点到汇点的通道,一个显而易见的结论是:st-剪切的流值等于这个网络流的值。更进一步,任何网络流的值都不会超过st-剪切的容量,这也意味着st-剪切代表着流网络的瓶颈,最小st-剪切的容量不会小于最大流的值,这个定理称为最大流-最小剪切定理。该定理也可以反过来表述:网络流的值最大不会大于任意一个给定的st-剪切的容量。当X只包含源点或Y只包含汇点时,最大流-最小剪切定理最为直观。
最小st-剪切代表补给线上最难走或最重要的路段,只要破坏这些路段,就能以最小的代价掐断敌军的补给,即使只破坏了一部分,也能有效降低敌军的补给能力。既然最小st-剪切和最大流存在关联关系,我们就可以在寻找最大流时顺带找出最小st-剪切,这仍然需要使用残存网。在残存网中,将源点和从源点出发可以到达的顶点看作集合X,剩下的顶点看作集合Y,对于边v→w,如果满足v属于X,w属于Y,那么v→w就是最小st-剪切中的一条边。
以下图为例,在残存网中源点能够到达的顶点只有v3,原网络的最小st-剪切是:

可以根据这种思路在FordFulkerson中添加寻找最小st-剪切的实现。
class FordFulkerson():
def __init__(self, G:Network):
self.G = G
self.max_flow = 0 # 最大流
…… (省略部分参考上一章的相关代码)
def min_st_cut(self):
''' 找到最小st-剪切 '''
X = [self.G.s] # st-剪切的X集合
stack = [self.G.s]
while len(stack) > 0:
v = stack.pop()
for e in self.G.edges_from(v): # 所有从v顶点流出的边
if e.w != self.G.t and e.w not in X and e.residual_cap_to(e.w) > 0:
X.append(e.w)
stack.append(e.w)
Y = list(set(self.G.V) - set(X)) # st-剪切的X集合
st_cut = [e for e in self.G.E if e.v in X and e.w in Y] # 连接X和Y的边
return X, Y, st_cut def display_st_cut(self, X, Y, st_cut):
print('X={0}, Y={1}'.format(X, Y))
print('st-cut={}'.format([str(e) for e in st_cut]))
min_st_cut使用深度优先搜索寻找最小st-剪切。由于这种方法需要借助残存网,因此在使用min_st_cut前需要首先执行一次计算最大流的操作。现在可以计算出乙军的轰炸目标了:

姜子牙的押粮官
在《封神演义》中,姜子牙经过金台拜将之后,担任“扫荡成汤天宝大元帅”一职,代武王伐纣。率领六十万西岐大军浩浩荡荡,东进朝歌。所谓“三军未动,粮草先行”,在临行前,姜子牙任命了四个先锋官的同时,又任命了杨戬、土行孙、郑伦三个押粮官。
押粮前必先征粮,单从一个地方征粮恐怕不足以支持一场灭国战争,假设下图是西岐的粮道。

边的容量代表粮道的运力,杨戬、土行孙、郑伦分别从三v1、v2、v3个征粮地同时出发,将粮草运往唯一的前沿阵地t,由于运粮过程中十分安全,所以三人可以在每个节点处合兵或分兵,怎样行进才能使粮道发挥出最大运力呢?
多个源点与多个汇点
问题可以规约成典型的最大流问题,但与之前介绍的st-网络不同,粮道图中有多个源点(或者说没有源点),如此一来将会对最大流的相关算法造成影响,怎么办呢?
其实很简单,在三个源点前再加入一个超级源点,这样一来v1、v2、v3就变成了普通的节点,它们也符合守恒定律,原网络也转换成了st-网:

与此类似,也可以通过建立一个超级汇点来处理多个汇点的情况。
粮道的最大运力
有了超级节点后,只要把初始数据输入交给计算机就可以了。
import network_flow as nf V = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
E = [nf.Edge(0, 1, 18), nf.Edge(0, 2, 18), nf.Edge(0, 3, 18), nf.Edge(1, 4, 9),
nf.Edge(1, 5, 9), nf.Edge(2, 5, 9), nf.Edge(2, 6, 9), nf.Edge(3, 6, 9),
nf.Edge(3, 7, 9), nf.Edge(4, 8, 3), nf.Edge(4, 9, 12), nf.Edge(5, 9, 6),
nf.Edge(5, 10, 14), nf.Edge(6, 10, 7), nf.Edge(6, 11, 5), nf.Edge(7, 11, 10),
nf.Edge(7, 12, 12), nf.Edge(8, 13, 8), nf.Edge(9, 13, 8), nf.Edge(10, 13, 8),
nf.Edge(11, 13, 8), nf.Edge(12, 13, 8)]
s, t = 0, 13
G = nf.Network(V, E, s, t)
ford_fullkerson = nf.FordFulkerson(G)
ford_fullkerson.start()
ford_fullkerson.display()
最大流是33,下图是根据程序运行结果映射的网络流。

最大流是确定的,但押粮路线并不是唯一的,最大流算法和边的输入顺序都会对它产生影响。对于增广路径最大流算法来说,寻找增广路径的算法也会影响最终的押粮路线。
作者:我是8位的
网络流(3)——找到最小st-剪切的更多相关文章
- Cogs 728. [网络流24题] 最小路径覆盖问题
[网络流24题] 最小路径覆盖问题 ★★☆ 输入文件:path3.in 输出文件:path3.out 评测插件 时间限制:1 s 内存限制:128 MB 算法实现题8-3 最小路径覆盖问题(习题8-1 ...
- cogs 728. [网络流24题] 最小路径覆盖问题 匈牙利算法
728. [网络流24题] 最小路径覆盖问题 ★★★☆ 输入文件:path3.in 输出文件:path3.out 评测插件时间限制:1 s 内存限制:128 MB 算法实现题8-3 最 ...
- 网络流 最大流—最小割 之SAP算法 详解
首先引入几个新名词: 1.距离标号: 所谓距离标号 ,就是某个点到汇点的最少的弧的数量(即边权值为1时某个点到汇点的最短路径长度). 设点i的标号为level[i],那么如果将满足level[i]=l ...
- 十依据一个有用的算法来找到最小(最大)的k的数量-线性搜索算法
例如:进入1.2.3,4,5,6.7.8此8数字,最小的4图的1,2,3,4. 思路1:最easy想到的方法:先对这个序列从小到大排序.然后输出前面的最小的k个数就可以.假设选择高速排序法来进行排序, ...
- 【BZOJ】2561: 最小生成树【网络流】【最小割】
2561: 最小生成树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2685 Solved: 1253[Submit][Status][Discu ...
- 【洛谷】4304:[TJOI2013]攻击装置【最大点独立集】【二分图】2172: [国家集训队]部落战争【二分图/网络流】【最小路径覆盖】
P4304 [TJOI2013]攻击装置 题目描述 给定一个01矩阵,其中你可以在0的位置放置攻击装置. 每一个攻击装置(x,y)都可以按照“日”字攻击其周围的8个位置(x-1,y-2),(x-2,y ...
- P2764 [网络流24题]最小路径覆盖问题[最大流]
地址 这题有个转化,求最少的链覆盖→即求最少联通块. 设联通块个数$x$个,选的边数$y$,点数$n$个 那么有 $y=n-x$ 即 $x=n-y$ 而n是不变的,目标就是在保证每个点入度.出度 ...
- P1361 小M的作物 【网络流】【最小割】
题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号). 现在,第i种作物种植在A中种植可 ...
- 【uva 1349】Optimal Bus Route Design(图论--网络流 二分图的最小权完美匹配)
题意:有一个N个点的有向带权图,要求找若干个有向圈,使得每个点恰好属于一个圈.请输出满足以上条件的最小权和. 解法:有向圈?也就是每个点有唯一的后继.这是一个可逆命题,同样地,只要每个点都有唯一的后继 ...
随机推荐
- 去掉烦人的“!=null"(判空语句)
文章首发于公众号 松花皮蛋的黑板报 作者就职于京东,在稳定性保障.敏捷开发.高级JAVA.微服务架构有深入的理解 为了避免空指针调用,我们经常会看到这样的语句 if (someobject != nu ...
- Linux 定位进程对应的文件路径
ls -al /proc/[pid]/exe # 例如: [root@localhost ~]# ls -al /proc/9109/exe lrwxrwxrwx. 1 ibaboss ibaboss ...
- MySQL问题记录——2003-Can't connect to MySQL server on 'localhost'(10038)
MySQL问题记录——2003-Can't connect to MySQL server on 'localhost'(10038) 摘要:本文主要记录了连接到MySQL数据库时出现的问题以及解决办 ...
- 跑健壮性Monkey,出现一次Crash全过程-日志分析-董浩-Dotest
最近带着学生做的某个项目,跑健壮性Monkey,出现一次Crash全过程-日志分析: 准备:搭建adb环境.安装实际测试包:开始: Monkey命令: 1 2 3 4 5 adb shell monk ...
- MongoDB学习笔记(三、MongoDB聚合与更新)
目录: 聚合 更新 更新选择器 ObjectId 更新操作的原子性 聚合: 聚合语法:db.collectionName.aggregate(aggregate_operation) 聚合操作其实就是 ...
- [C5W3] Sequence Models - Sequence models & Attention mechanism
第三周 序列模型和注意力机制(Sequence models & Attention mechanism) 基础模型(Basic Models) 在这一周,你将会学习 seq2seq(sequ ...
- Servlet一次乱码排查后的总结
由来 在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出来的中文显示到页面正常,锁定肯定是request对象那里出了问题.后来经过排查,发现是我封 ...
- Codeforces Round #598 (Div. 3) D. Binary String Minimizing 贪心
D. Binary String Minimizing You are given a binary string of length n (i. e. a string consisting of ...
- js input radio点击事件
html代码: <input type="radio" name="myname" value="1" />1 <inpu ...
- 6 种微服务 RPC 框架,你知道几个?
开源 RPC 框架有哪些呢? 一类是跟某种特定语言平台绑定的,另一类是与语言无关即跨语言平台的. 跟语言平台绑定的开源 RPC 框架主要有下面几种. Dubbo:国内最早开源的 RPC 框架,由阿里巴 ...
