图与网络分析—R实现(五)

四 最大流问题

最大流问题(maximum flow problem),一种网络最优化问题,就是要讨论如何充分利用装置的能力,使得运输的流量最大,以取得最好的效果。最大流问题是一类应用极为广泛的问题,例如在交通网络中有人流、车流、货物流,供水网络中有水流,金融系统中现金流,等等。

1. 最大流问题的描述

(1)容量网络:一个图是由点集V={vi}和V中元素的无序对的一个集合E={ek}所构成的二元组。仅有一个入次为0的点vs称为发点(源),一个出次为0的点vt称为收点(汇),其余点为中间点,这些边上面载荷为容量或流量,这样的网络G称为容量网络,常记做G=(V,E,C)。
(2)容量和流量:设有向连通图G=(V,E),G的每条边(vi,vj)上的非负数cij称为边的容量。对任一G中的边(vi,vj)有流量fij,称集合f={fij}为网络G上的一个流。图1即为一个有向连通图,括号中第一个数字代表容量,第二个数字代表流量。
(3)可行流:称满足下列两个条件的流为可行流:容量限制条件:对G中的每条边(vi,vj),有0≤fij≤cij;即每条边上的流量非负而且最大也只能达到容量的限制;平衡条件:对中间点vi,有即物资的输入量和输出量相等。对发、收点vs,vt,他们进来或出去流量总和为网络流的总流量。
(4)割(截)集和截量:容量网路G=(V,E,C),vs,vt为发、收点,若有边集E'为E的子集,将G为两个子图G1,G2,即点集V被剖分为两个顶点集合。若有边集E'为E的子集,满足:若把整个截集的弧从网络G=(V,E,C)中丢去,则不存在从vsvt的有向路,即图(V,E-E')不连通;只要没把整个截集删去,就存在从vsvt的有向路,即当E'为E的真子集,图G(V,E-E')仍连通,则称E'为G的割集(也称截集),它将容量网络分为互补的两部分。截集中边的容量之和称为该截集的截量。

最大流-最小截集理论

在容量网络中截集是由vsvt​的必经之路,所以任何一个可行流的流量都不会超过任一截集的容量。因此若能找到一个可行流的流量等于某一割集的容量,则该可行流为最大流,相应的割集为最小割。以下图为例,每条边上的前一个数字表示流量限制,括号里数字表示初始可行流,从图中可知,容量网络G的割集有很多个,其中割集容量最小就成为网络G的最小割集容量(简称最小割)。

2. 最大流问题算法

从可行流和可增广链关系来看,就可以知道一种寻求最大流的方法:从一个可行流开始,寻求关于这个可行流的可增广链,若存在,则可以经过调整,得到一个新的可行流,其流量比原来的可行流要大,重复这个过程,直到不存在关于该流的可增广链时就得到了最大流。 求最大流的标号算法最早由福特和福克逊于1956年提出,20世纪50年代福特(Ford)、福克逊(Fulkerson)建立的“网络流理论”,标号的方法可分为两步:第一步是标号过程,通过标号来寻找可增广链;第二步是调整过程,沿可增广链调整f以增加流量。

标号过程

(1)给发点(始点)以标号(△,+∞)或(0,+∞)。
(2)选择一个已标号的顶点vi,对于vi的所有未给标号的邻接点vj按下列规则处理:(a)若后向边(vj,vi)∈E,且fji>0时,则令δj=min(fji,δi),并给vj以标号(-vi,δj),这表明vj点的vi点的边最多可以减少δj的流量以提高整个网络的流量。(b)若前向边(vi,vj)∈E,且fij cij时,令δj=min(cij-fij,δi),并给vj以标号(+vi,δj),这表明vi点到vj点的边最多可以增加δj的流量以提高整个网络的流量。括弧内的第一个数字表示这个节点得到的得到标号前的第一个结点的代号,第二个数字表示从上个标号节点到这个标号节点允许的最大调整量δ,假定发点的调整量不限,所以标记为+∞。
(3)重复(2)直到收点vt被标号或不再有顶点可被标号为止。
若vt没有得到标号,说明标号过程已无法进行,可行流f已是最大流。若vt得到标号,说明存在一条可增广链,转入调整过程。标号若有多条增广链时,不用刻意考虑哪种调整更适合,只需一条一条地转入调整过程,不用全盘考虑。

调整过程

(1)令这条被找到的增广链中所有的前向弧全部加上δj的流量,所有的后向弧全部减去δj的流量,至于不在增广链之中的边的流量则不需要调整。
(2)去掉所有标号,回到第1步,对可行流f'重新标号。

3. 最大流问题R程序

library('igraph')
##容量网络的构建为——输入的数字为容量
r1 = c(0,5,4,3,rep(0,4))    
r2 = c(rep(0,4),0,3,0,0)
r3 = c(rep(0,5),3,2,0)
r4 = c(rep(0,6),2,0)
r5 = c(0,5,rep(0,5),4)
r6 = c(rep(0,7),3)
r7 = c(rep(0,7),5)
r8 = rep(0,8)
adj = rbind(r1,r2,r3,r4,r5,r6,r7,r8)
g = graph.adjacency(adj, mode = c('directed'), weighted = TRUE) 
plot(g,edge.label = get.data.frame(g)[,3],layout=layout.auto)

vcount(g)  #顶点数
ecount(g)  #边数
E(g)  #边的方向
E(g)$weight  #表示每条边的最大承载力(流量限制)
flow1 = graph.maxflow(g,1,8,E(g)$weight)  #计算源点1到汇点8的最大流
flow1

4. 最大流问题R计算结果

$value
[1] 7       #计算得出最大流量为7
$flow
 [1] 3 2 2 3 0 2 2 0 0 3 4
$cut
[1]  6  7 10
$partition1
+ 5/8 vertices, from b8f4e9f:
[1] 1 2 3 4 6       #截集源阵营包含的节点
$partition2
+ 3/8 vertices, from b8f4e9f:
[1] 5 7 8           #截集汇阵营包含的节点

5. 结果可视化

V(g)[flow1$partition1]$color="green"
V(g)[flow1$partition2]$color="red"
plot(g,edge.label = get.data.frame(g)[,3],layout=layout.auto)
#红色顶点和绿色顶点之间的边就是截集中的边(这些边都要求是正向边,从源这边流向汇那边,下图中节点5-2是反向边,不算在截集里);红色顶点和绿色顶点之间的边的容量之和就是截量

6. 最大流问题的应用

某河流中有四座岛屿,从两岸至各岛屿及各岛屿之间的桥梁我们进行编号区分。现有一持枪嫌疑犯在A岸作案后,动向不明。估计他们要向F岸逃窜,问应至少在几座桥上设卡,才能完全切断两岸的陆上交通联络这是一个交通网络。我们将两岸和岛屿用点表示,相互间有桥梁联系的用线表示画出网络图。图中连线方向根据从A出发通向F方向来定。因A至F方向不通的话,则从F至A方向也不通。各线路的容量转化为两点之间的桥梁数。要求切断两岸的交通联系的最小桥梁数,就是要卡这个交通网的脖子,就相当求该网络的最小截集。
在抗洪、抢险救灾等非常时期,我们可能还会担负着各种线路、管网的建设这类型任务。网络的最小截集是网络的咽喉或瓶颈,最小截集的容量大小影响网络总的输送量的提高,比如要改善公路网输送能力,必须首先考虑提高最小截集中各弧的容量大小,否则首先去提高其他弧的容量大小,是做无用功。找到最小截集后,可以扩路或在两地之间再加修一条路的方式去解决,都可以增大弧的容量。

参考文献

运筹学-图论实例

posted @   郝hai  阅读(591)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示