初识网络流(Ford-Fulkerson算法,Edmonds-Karp 最短增广路算法,Dinic 快速网络流算法)

127 篇文章 0 订阅
85 篇文章 2 订阅

今天!蒻终于知道了什么是网络流!!
对于一个源点和一个汇点,之间有许多条有一定容量的边,问单位时间内从源点到汇点最多可以流过多少流量。
这里写图片描述
就拿这张图来说,就是问从源点 s s s到汇点 t t t单位时间内的最大流量。
那对于最大流问题,有什么解决方法呢?

Ford-Fulkerson算法

基本思想就是每次用 d f s dfs dfs从源点开始搜索,直到汇点停止,这之间所经过的边中容量最小的一条边就是每次次 d f s dfs dfs所搜索到的容量,然后每次在搜索到汇点之后,对于路径上的每条边,都要减去本次搜索到的流量,最后直到找不到可行路径,每次 d f s dfs dfs搜索到的流量加起来就是从源点到汇点的最大流。但是这样做是存在一些问题的 。
这里写图片描述
就拿这个图来说,如果我们从 A → B → C → D A\to B\to C\to D ABCD这样走的话,我们最终得到的最大流只能是 100 100 100,但是实际上我们可以走 A → B → D A\to B\to D ABD A → C → D A\to C\to D ACD这两条,这样最大流就是 200 200 200。所以说,我们只是简单 d f s dfs dfs的话,我们就有可能过早的认为 B → C B\to C BC流量不为 0 0 0,因而在一次 d f s dfs dfs之后将 B → C B\to C BC变为了 0 0 0,使得 d f s dfs dfs找不到可行路了。所以改进方法就是在每次 d f s dfs dfs之后给路径的每一条边加一条反向边。反向边的容量和上次 d f s dfs dfs刚找到这条边时的容量相等。这样我们就可以利用这条反向边和剩余的边继续寻找可行路。(至于为何添加反向边这种操作是正确有效的,日后有时间再补,(^_^) 嘻嘻……)
这里写图片描述
添加反向边之后我们就可以走 A → C → B → D A\to C\to B\to D ACBD这条路,然后总流量就变为了 200 200 200,再次添加反向边,就没有可行路了,所以算法结束,最大流为 200 200 200

但是,这种算法同样存在缺陷,就是对于下面这张图
这里写图片描述
我们最坏可能要进行 200 200 200 d f s dfs dfs,因为只要走 B → C B\to C BC这条路,就算添加反向边,每次总流量也只是添加 1 1 1而已。
算法复杂度为 Θ ( C ∗ ( m + n ) ) = Θ ( C ∗ n 2 ) \Theta(C*(m+n))=\Theta(C*n^2) Θ(C(m+n))=Θ(Cn2) C C C d f s dfs dfs运行次数, m m m为边数, n n n为顶点数。

Edmonds-Karp 最短增广路算法

这种算法很好的避免了上述情况,每次找可行路增广时,选择从源点到汇点具有最少边的路径,利用 b f s bfs bfs找增广路径。

Dinic 快速网络流算法

上一种算法,每次增广的时候都要进行一次 b f s bfs bfs D i n i c Dinic Dinic算法又很好的优化了这个算法,在每一次进行增广的时候,用 d f s dfs dfs寻找多条增广路。

首先,利用 b f s bfs bfs对残余网络进行分层,
这里写图片描述
一个节点的层数就是源点到它需要经过的最少边数。
这里写图片描述
在分层完毕之后,利用 d f s dfs dfs做我们前面说的寻找增广路径,增加总流量的值,并且消减路径各边的容量,添加反向边。但是,前面每次碰到汇点之后就停止了,这里我们并不立即停止,而是进行回溯,我们应该回溯到哪个节点呢?我们应该回溯到的节点必须是搜索树中边 ( u , v ) (u,v) (u,v)的容量为 0 0 0并且最上层的节点
为什么?
因为 d f s dfs dfs找到增广路径添加反向边消减路径各边容量之后,有些边可能就为 0 0 0了,如果我们回溯到的不是最上层,那么我们再次进行 d f s dfs dfs找出的增广路径所增加的流量一定是 0 0 0!你们猜是否会找不到容量为 0 0 0的边呢?一定会的!想一下,我们前面每次 d f s dfs dfs所增加的流量,是由增广路径中容量最小的一条边决定的,所以说我们消减容量的话,一定会将增广路径中那条容量最小的边容量变为 0 0 0,因此我们一定可以找到这条边。
如果 d f s dfs dfs回溯到源点,并且无法往下走的时候, d f s dfs dfs结束。
d f s dfs dfs结束之后,再次用 b f s bfs bfs对残余网络进行分层,直到分层操作无法算出汇点的层次之后(即 b f s bfs bfs无法到达汇点时),算法结束,最大流求出。
D i n i c Dinic Dinic复杂度是 Θ ( n ∗ n ∗ m ) \Theta(n*n*m) Θ(nnm) ( n (n (n是点数, m m m是边数 ) ) )

靴靴各位巨巨观看!蒻初学,若有错误还请指出!^_^
(本文图片均来自于在 P K U PKU PKU暑期上课期间的 P P T PPT PPT

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Ford-Fulkerson算法是一种解决最大问题的算法,它通过不断寻找广路径来量,直到无法找到广路径为止。在Matlab中,可以使用图论工具箱中的函数来实现Ford-Fulkerson算法,例如使用graph和maxflow函数。具体实现方法可以参考Matlab官方文档或相关教程。 ### 回答2: Ford-Fulkerson算法是求解最大问题的一种经典算法,用于确定一个网络中从源节点到汇节点的最大可行量。下面我将简要介绍如何使用Matlab实现Ford-Fulkerson算法。 首先,我们需要定义一个图结构来表示网络。可以使用邻接矩阵来表示有向图,其中矩阵元素表示边的容量。源节点可以用一个预先定义的节点索引表示,汇节点也可以用另一个预先定义的节点索引表示。 接下来,我们可以实现Ford-Fulkerson算法的关键步骤。算法的主要思想是在剩余网络上找到广路径,并在这条路径上量,直到不能找到广路径为止。 具体实现中可以使用深度优先搜索(DFS)或广度优先搜索(BFS)来找到广路径。在每一次搜索过程中,我们需要判断当前节点是否已经被访问过,并且是否还可以通过当前边量。 在找到广路径后,我们可以计算出该路径上的最小容量(也称作瓶颈容量),并将该容量从剩余网络中减去。随后,我们将该容量添加到网络中,并继续寻找新的广路径。 当无法找到广路径时,算法结束并返回最大量值。最大量值等于从源节点发出的所有量之和。 综上所述,以上是在Matlab中实现Ford-Fulkerson算法的基本步骤。当然,具体实现中还需要考虑一些细节问题,并且可能需要调用一些Matlab内置的图算法函数来辅助实现。 ### 回答3: Ford-Fulkerson算法是用于求解最大问题的一种常见算法,适用于有向图。算法的基本思想是不断在剩余网络中寻找一条广路径,然后更新量分布,直到无法找到广路径为止。 在MATLAB中,可以使用图算法工具箱中的函数来实现Ford-Fulkerson算法。具体步骤如下: 1. 首先,需要创建一个有向图对象,并定义图中的节点和边。可以使用Graph对象来进行操作。 2. 然后,设置源节点和汇节点,即确定最大的起点和终点。 3. 接下来,需要定义图中各个边的初始容量。可以使用addedge函数来添加边,并设置其容量。 4. 之后,可以使用fordfulkerson函数来求解最大。该函数会返回一个最大值,同时也会更新图中各个边的量。 5. 最后,可以使用findedge函数来查找某条边的量。该函数需要指定边的起点和终点节点,返回对应边的量值。 需要注意的是,Ford-Fulkerson算法的复杂度较高,最坏情况下为O(f * m),其中f为最大值,m为边的数量。因此,在处理大规模图的情况下可能会面临一定的挑战。 以上是用MATLAB实现Ford-Fulkerson算法的简要过程。通过使用MATLAB的图算法工具箱,可以方便地对最大问题进行求解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值