基于Floyd算法的最小费用流的负回路算法(图解)

本文介绍了如何运用Floyd算法解决最小费用流问题,通过构建容量-费用网络,确定最小费用流的定义,并提供一种通过最大流算法找到初始可行流的方法。接着,通过寻找并增加负回路的流量来不断优化费用,直至无法找到负回路。Floyd算法在此过程中用于检测负回路,从而达到最小化总费用的目的。

屈婉玲《算法设计与分析》第2版第7章网络流算法学习笔记。

概述

最小费用流问题,可视为一般化的最短路径问题最大流问题,即只要选定合适的权重、容量、流量,解决最小费用流的方法就能用来解决上述问题。另一方面,也意味着解最小费用流问题至少和解最短路径或最大流问题一样难。

显然可以用来解决物流运输最小成本问题,除此之外还有广泛应用,比如劳动力分配问题:

劳动力和任务间用边连接,费用为工人对任务的讨厌程度(当不可能干某任务时可以是∞),流量是完成任务需要的小时数。

定义

容量-费用网络:N={V, E, c, w, s, t}
在容量网络N={V, E, c, s, t}中,添加单位费用w,将其称作容量-费用网络。

费用:w(f)
设f是N上的一个可行流,w(f)=∑ w(i, j) * f(i, j) 为f的费用。

流量v0的最小费用流:
给定流量v0的可行流中,费用最小的称作流量v0的最小费用流。

算法思想

先任意找出一个流量为v0的可行流。如何找呢?利用最大流算法,找出最大流f,若v(f)<v0,最大流量都达不到v0,说明无解;若v(f)>=v0,只需将v(f)修剪成与v0相等即可。

接下来构造残余容量网络:前向边的残余容量为c - f,后向边的残余容量为f;前向边的费用为w, 对应后向边的费用为-w。

前向边表示增加流会发生什么,后向边表示减少流会发生什么。

寻找一个有正向残余容量和负代价的回路(负回路),尽可能增加回路上的流量(增加前向边的流量,减少后向边的流量)。重复上述操作直到找不到负回路为止。

关键便是寻找负回路。“回路”意味着流量不用额外增加或减少,“负”意味着流量越大费用越小。要想求最小费用流,只需将所有负回路上的流量调到最大即可。

如何找负回路呢?Floyd算法可以完美解决,参考:多源最短路径Floyd算法(可用于找负回路) C++实现

例子

  1. 给定容量-费用网络N及其流量v0=8的可行流f,此时w(f) = 5 * 3 + 3 * 3 + 5 * 3 + 3 * 1 = 42
    在这里插入图片描述
  2. 构造残余网络N(f),找出一个负回路C,辅助费用aw = -1(回路费用和1+1-3 = -1),环流量 = 3(残余容量所能承载的最大值,回路残余容量分别为3、3、5),圈流h = 3 * -1 = -3
    在这里插入图片描述
  3. 更新流f1 = f + h,w(f1) = 42 - 3 = 39
    在这里插入图片描述

算法

伪代码

1. 调用一次最大流算法,求v0的一个可行流f;若最大流小于v0,则输出“无可行流”结束算法
2. 构造N(f)
3. 用Floyd算法检测N(f)中是否存在负回路,若没有则输出f结束算法
4. 令d←min{ac(i, j)<i, j> ∈ E(C)}  //hc的环流量为d
5. 若<i, j> ∈ E, 令f(i, j) ← f(i, j) + d;<j, i> ∈ E, 令f(j, i) ← f(j, i) - d
6. 重复步骤2
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值