最短增益路径法求解最大流问题(可随机生成有向图)

本文介绍了使用最短增益路径法求解最大流问题的算法思想,包括网络存储、残留网络计算、节点标注以及查找增广路径的流程。通过随机生成有向图,并利用前向边和反向边确定最小流量,逐步找到最大流。在处理过程中,还考虑了避免孤点的策略,并在无法找到最大流时重新生成图以确保连通性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法思想:

解决最大流问题我们可以利用增广路径来增加流量,然后通过一次次的迭代将增光路径全部找出,此时从源点出发的流量和就是此网络的最大流量。而确定每一次增广路径的流量都需要用到残留流量等方法计算。以下就是将这个方法的具体实现算法展现出来:

 

1、将流网络用矩阵数组的方式存储。如共有n个点则创造一个n*n的数组a,每个数组的值都表示那条路径的权重,如a[1][3]的值若不为0则表示从点1到点3有路径。其中特别注意的是有以下几点:(1)、矩阵中无任何边指向源点,汇点也无任何边指其他点。即矩阵的第一列和最后一行均为0。(2)、矩阵中无两条平行反向边,如1指向3后3不能指向1。(3)、自己不能形成环,即自己出去的边不能指向自己。

为了预防孤点(无边指向且无边指出),我在生成随机图时将边平均分到每个顶点中,如假设有100条边11个顶点,则每个顶点肯定有指出去的边9条,这样就很大概率上防止了孤点的存在。然后多余的1条边再随机分配给顶点。

 

2、残留网络则是通过当前流量数组间接计算得出,当前流量数组是个n*n数组,初始化将数组内容都设为0。当一条增广路径找到并计算出此路径的流量后,修改相对应的数组内的流量。然后残余流量就是将相对应的边流量减去当前流量得到。

 

3、对于节点的标注也是放到一个n*3的数组中。其中n表示节点总个数。第一列表示到达此节点的流量,第二列表示此节点的父节点,第三列表示流的方向(若是正向边流入则表示为1,若是为反向边则表示为-1)。初始化除了源点外的每个节点初始化的流量和方向均为0,父节点为-1。因为源点的特殊性所以将源点的父节点设为-2,以便和其他节点区分开。

 

以上是预处理部分,接下来就是算法的核心部分:如何查找增广路径及每次迭代的最小流量。

 

4、首先建立一个空队列,用于存放每次标记的节点。第一次将源点放入此队列中。以后取节点操作都是对队列进行。

 

5、每次都先取队列的第一个节点,然后开始从流数组中查看此节点指向哪些节点,若被指向的节点未被标记(父节点为0)且残余流量大于0,则将被指向的节点进行标记(第一列流量改为能通过的最小流量,第二列父节点改为刚刚取得的节点,第三列改为1表示是正向边)后放入队列。循环做此步直至当前节点所指向的点全部标记且入队列。

前向边获得最小流量是将当前边的总流量减当前流量,得到残余流量。若残余流量大于0,则与当前的最小流量比较,若小于最小流量则此残余流量设为最小流量。

 

6、将当前节点的前向边遍历结束后开始判断反向边(即是否有未标记的节点指向当前节点),若存在反向边则将流出流的节点进行标记(第一列流量改成最小流量,第二列父节点改成当前节点,第三列改成-1表示反向边)后放入队列。循环做此步直到所有反向边被遍历完毕。

反向边获得最小流量的方法与前向边不同,是直接判断此反向边的当前流量是否大于0,若是则当前流量与最小流量比,获得小的数作为最小流量。

 

7、每次遍历和标记完一个节点的所有前向边和后向边后,检查汇点是否被标记,若没被标记则继续取队列的下一个节点;若被标记则表示一条增广路径已被找到,此条路径上的所有当前流量都改为当前最小流量(即当前流量数

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值