屈婉玲《算法设计与分析》第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++实现
例子
- 给定容量-费用网络N及其流量v0=8的可行流f,此时w(f) = 5 * 3 + 3 * 3 + 5 * 3 + 3 * 1 = 42

- 构造残余网络N(f),找出一个负回路C,辅助费用aw = -1(回路费用和1+1-3 = -1),环流量 = 3(残余容量所能承载的最大值,回路残余容量分别为3、3、5),圈流h = 3 * -1 = -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
本文介绍了如何运用Floyd算法解决最小费用流问题,通过构建容量-费用网络,确定最小费用流的定义,并提供一种通过最大流算法找到初始可行流的方法。接着,通过寻找并增加负回路的流量来不断优化费用,直至无法找到负回路。Floyd算法在此过程中用于检测负回路,从而达到最小化总费用的目的。
1031

被折叠的 条评论
为什么被折叠?



