蓝桥杯-网络流裸题
1|0题目:
一个有向图,求1到N的最大流
输入格式:
第一行N M,表示点数与边数
接下来M行每行s、t、c。表示一条从s到t的容量为c的边
输出格式:
一个数最大流量
样例输入:
样例输出
数据约定:
2|0预备知识和注意事项:
考虑如下情境:
在某个污水处理厂的某一道程序里,有一个「进水孔」,和一个「排水孔」,中间由许多「孔径不一」的水管连接起来,因为水管的「孔径大小」会影响到「每单位时间的流量」,因此要解决的问题,就是找到每单位时间可以排放「最大流量( flow )」的「排水方法」。
以图一为例,进水孔为vertex(S)
,排水孔为vertex(T)
,中间要经过污水处理站vertex(A)
与vertex(C)
边(edge)代表水管,边的权重(weight)(以下将称为capacity )表示水管的「孔径」。
考虑两种「排水方法」的flow:
-
第一种分配水流的方法,每单位时间总流量为
20
:- 在Path :
S − A − T
上每单位时间流了5
单位的水; - 在Path :
S − A − C − T
上每单位时间流了10
单位的水(问题出在这,占去了edge(C,T)的容量); - 在Path :
S − C − T
上,因为edge(C,T)上只剩下「5
单位的容量」,因此每单位时间流了5
单位的水。
- 在Path :
-
第二种分配水流的方法,每单位时间总流量为
25
:- 在Path :
S − A − T
上每单位时间流了10
单位的水; - 在Path :
S − A − C − T
上每单位时间流了5
单位的水; - 在Path :
S − C− T
上,因为edge(C,T)上刚好还有「10
单位的容量」,因此每单位时间流了10
单位的水;
- 在Path :
从以上两种「排水方式」可以看得出来,解决问题的精神,就是如何有效利用水管的「孔径容量」,让最多的水可以从「进水孔」流到「排水孔」。
这就是在网络流(Flow Networks)上找到最大流量( Maximum Flow )的问题。
3|0网络流的基本性质
Flow Networks
是一个带权有向图,其edge(X,Y)
具有非负的capacity,即:c(X,Y)≥0
,如图二(a)。我们可以利用一个矩阵存储图信息。
- 若不存在
edge(X,Y)
,则定义c(X,Y) = 0
- 特别的,要区分两个
vertex
:source
:表示Flow Networks
的流量源头,以s
表示。sink/termination
:表示Flow Networks
的流量终点,以t
表示。
- 水管里的水流:
flow
,必须满足以下三个条件a.容量限制 b.反对称性 c.流守恒性
:- 从顶点X流向顶点Y的流 <=
edge(X,Y)
的capacity
- 以图二(b)为例,在Path : S − A − C − D − T上的edge之capacity皆大于6,因此在此路径上流入
6
单位的flow
是可行的。最小的f(X,Y) = 7
,所以流过的flow只要小于等于7
即可。
- 以图二(b)为例,在Path : S − A − C − D − T上的edge之capacity皆大于6,因此在此路径上流入
f(X,Y) = -f(Y,X)
,此与电子流(负电荷)与电流(正电荷)的概念雷同- 对有向图中除了
source
与sink
以外的顶点而言,所有「流进flow」之总和 = 所有「流出flow」的总和
。也就是水流不会无故增加或无故减少,可视为一种守恒。
- 从顶点X流向顶点Y的流 <=
- 可行流:在容量网络中满足以下条件的网络流flow,成为可行流
- 弧流量限制条件:
0 <= f(u,v) <= c(u,v)
- 平衡条件:即流入一个点的流量要等于流出这个点的流量。(
source
和sink
除外)
- 弧流量限制条件:
4|0最大流量算法(Ford-Fulkerson算法)
Ford-Fulkerson算法需要两个辅助工具
- Residual Networks(剩余网路,残差图)
- Augmenting Paths(增广路径)
4|1Residual Networks(剩余网路,残差图)
Residual Networks的概念为:记录Graph上之edge还有多少「剩余的容量」可以让flow流过。
以图三为例:
-
如果在Path:
S - A - C - D - T
上所有的edge都有6
单位的flow流过,那么这些edge(edge(S,A)、edge(A,C)、edge(C,D)、edge(D,T))可用的剩余capacity
,都应该减6
。例如:edge(S,A)只能在容纳9-6=3
单位的flow,edge(C,D)只能容纳7-6=1
单位的flow。 -
最关键的是,若「从vertex(A)指向vertex(C )」之
edge(A,C)
上,有6
单位的flow流过,即f(A,C)=6
,那么在其Residual Networks
上,会因应产生出一条「从vertex(C ) 指向vertex(A)」的edge(C,A),并具有6单位的residual capacity,即:cf(C,A) = 6
。 (证明见下) -
证明:这些
residual capacity
称为:剩余capacity
以cf
表示。-
cf(C,A) = c(C,A) - f(C,A) = c(C,A) + f(A,C) = 0+6 = 6
-
其物理意义:可以用重置配置水流方向来理解。
-
根据上图表示,我们可以将其看成是:我们已经有了一个通过
6
个单位的流量的剩余网络,如果现在想经过Path:S - C - A - B - T
流过2
单位的flow。 -
根据上图画出的残差图为:
-
在图三(a)已经有
6
单位的流从顶点A流向顶点C,现在可以从edge(A,C)上把2
单位的flow"收回",转而分配到edge(A,B)上,而edge(A,C)上就只剩下4
单位的流,最后的结果如下图所示:我们根据上图可以看出:流入
sink (或称termination)
的flow累加到8单位。
-
-
综上:
- 若edge(X,Y)上有flow流过,即f(X,Y),便将edge(X,Y)上的
Residual Capacity
定义为:cf(X,Y) = c(X,Y) - f(X,Y)
c(X,Y)
表示原来水管孔径大小;f(X,Y)
表示目前水管已经有多少容量;cf(X,Y)
表示水管还能在容纳多少流量;
- 若edge(X,Y)上有flow流过,即f(X,Y),便将edge(X,Y)上的
4|2Augmenting Paths(增广路径)
在Residual Networks
里,所有能够「从source走到termination」的路径,也就是所有能够「增加flow的path」,就称为Augmenting Paths
。
4|3演算法
Ford-Fulkerson Algorithm (若使用BFS搜寻路径,又称为Edmonds-Karp Algorithm)的方法如下:
- 在
Residual Networks
上寻找Augmenting Paths
- 若以BFS方法寻找,便能确保每次找到的
Augmenting Paths
一定经过最少的edge。(对于所有边长度相同的情况,比如地图模型,bfs第一次遇到目标点,此时就一定是从根节点到目标节点最短的路径【因为每一次所有点都是向外扩张一步,你先遇到就一定是最短】。bfs先找到的一定是最短的)。
- 若以BFS方法寻找,便能确保每次找到的
- 找到
Augmenting Paths
上的最小Residual Capacity
加入总flow,在以最小Residual Capacity
更新Residual Networks
的edge的Residual Capacity
。 - 重复上述步骤,知道再也没有
Augmenting Paths
为止,便能找到最大流。
5|0例子:
STEP-1:先用flow = 0
对Residual Capacity
进行初始化,如图五(a)
STEP-2:在Residual Networks
上寻找Augmenting Paths
在该Graph中,使用BFS寻找能够从顶点S到顶点T,且edge数最少
的路径,PATH = S - A - B - T
,见图五(b)。BFS有可能找到其他一条S - C - D - T
,这里以前者为例:
STEP-3:找到Augmenting Paths
上的最小Residual Capacity
加入总flow
最小Residual Capacity
= 3;
flow = flow + 3;
STEP-4:以最小Residual Capacity
更新Residual Networks
上的edge之residual capacity
重复上述操作,对上述残差图继续寻找增广路径,直到找不到增广路径为止。
6|0代码:
-
建立有向图Graph,并使用
graph[X][Y]
保存edge(X,Y)的权重weight
-
使用BFS方法进行搜索,寻找从
source
到sink
的路径,而且是edge
数量最少的路径: -
找到从BFSFindPath()找到的路径上,最小的
Residual capacity
。 -
演算法的思路:
-
完整代码:
__EOF__

本文链接:https://www.cnblogs.com/guosiliang/p/13794279.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现