使用贝尔曼-福特算法求解图的最小费用最大流问题

给定一个源节点 S, 一个汇节点 T,以及两个表示图的矩阵 Cap[ ][ ]Cost[ ][ ]。其中,Cap[i][j] 是从节点 i 到节点 j 的有向边的容量,而 cost[i][j] 是从节点 i 到节点 j 沿有向边发送单位流的成本。我们的任务是从给定的图中找到一个具有最小费用最大流的可行流。

> 最小费用最大流: 从给定图中输送尽可能最大的流量所需的最小成本(每单位流)。

示例:

> 输入: S = 0, T = 4, cap[ ][ ] = {{0, 3, 4, 5, 0}, {0, 0, 2, 0, 0}, {0, 0, 0, 4, 1}, {0, 0, 0, 0, 10}, {0, 0, 0, 0, 0}},

> cost[ ][ ] = {{0, 1, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}

> 输出: 10 1

> 解释:

> 对于给定的图,最大流 = 10,最小费用 = 1。

>

>

>

> 输入: S = 0, T = 4, cost[][] = { { 0, 1, 0, 0, 2 }, { 0, 0, 0, 3, 0 }, { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0 } }

> cap[][] = { { 0, 3, 1, 0, 3 }, { 0, 0, 2, 0, 0 }, { 0, 0, 0, 1, 6 }, { 0, 0, 0, 0, 2 }, { 0, 0, 0, 0, 0 } }

> 输出: 6 8

解决思路:

成本网络中的负环是指环路中所有边的成本之和为负的环。我们可以使用 Bellman Ford 算法 来检测它们。必须消除这些负环,因为在实际应用中,不允许流量通过这样的循环。考虑一个 负费用环,如果所有流量都必须通过这个环,那么每完成一个循环,总成本就会不断降低。为了 最小化总成本,这将导致一个无限循环。因此,每当成本网络包含负环时,这意味着成本还可以进一步降低(通过流经环的另一侧,而不是当前考虑的一侧)。一旦检测到负环,就会通过让 瓶颈容量#:~:text=In%20production%20and%20project%20management, customers%2C%20and%20low%20employee%20morale.) 的流量通过环中的所有边来将其消除。

现在,让我们来看看什么是供应节点和需求节点:

> 供应节点: 这些是添加到流中的正节点,它们产生流量。

> 需求节点: 这些是从流中减去的负节点。

> 每个节点的供应(或需求) = 流出节点的总流量 – 流入节点的总流量

我们通过向环路中的所有边发送瓶颈容量来处理负环,从而解决给定的问题。此外,由于涉及需求节点,我们会调用 Bellman Ford 算法

请按照以下步骤解决问题:

  • 边的容量边的成本 存储在两个独立的数组中。
  • 给定源节点 S 和汇节点 T,选取的边 pi,需求节点 da 以及节点之间的距离 dist,搜索是否存在从 ST 的流。
  • 如果流存在,则计算距离,value = dist + pi – pi[k] – cost[k]
  • dist[ ] 中的距离值与 value 进行比较,并持续更新直到获得 最小流

下面是上述方法的实现:

C++


#include

#include

#include

using namespace std;

// Stores the found edges

vector found;

// Stores the number of nodes

int N = 0;

// Stores the capacity of each edge

vector<vector> cap;

vector<vector> flow;

// Stores the cost per unit flow of each edge

vector<vector> cost;

// Stores the distance from each node

// and picked edges for each node

vector dad, dist, pi;

const int INF = INT_MAX / 2 – 1;

// Function to check if it is possible to

// have a flow from the src to sink

bool search(int src, int sink) {

// Initialise found[] to false

found = vector(N, false);

// Initialise the dist[] to INF

dist = vector(N + 1, INF);

// Distance from the source node

dist[src] = 0;

// Iterate until src reaches N

while (src != N) {

int best = N;

found[src] = true;

for (int k = 0; k < N; k++) {

// If already found

if (found[k])

continue;

// Evaluate while flow

// is still in supply

if (flow[k][src] != 0) {

// Obtain the total value

int val = dist[src] + pi[src] – pi[k] – cost[k][src];

// If dist[k] is > minimum value

if (dist[k] > val) {

// Update

dis

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/32609.html
点赞
0.00 平均评分 (0% 分数) - 0