了解福特-福克森算法

    在本教程中,您将学习什么是Ford-Fulkerson算法。此外,您还将找到在C语言的示例。
    Ford-Fulkerson算法是一种计算网络或图中最大流量的贪心方法。
    术语流量网络(flow network),用来描述一个由顶点和边组成网络,该网络使用源节点(S)和汇聚节点(T)描述边。每个顶点,除了S和T,都可以接收和发送等量的内容。S只能发送,T只能接收。
    我们可以在不同容量的管道网络中使用液体流来可视化对算法的理解。每根管道都有一定容量的液体,它可以在一个实例中传输。对于福特-福克森算法,我们要找出在一个实例中,有多少液体可以从网络的源节点流向汇聚节点。
在这里插入图片描述

使用的术语

增广路径
    它是流网络中可用的路径。
残差图
    它表示具有其他可能流量的流量网络。
剩余容量
    从最大容量中减去流量后的边缘容量。

Ford-Fulkerson算法如何工作?

    该算法如下:

  1. 将所有边中的流量初始化为0。
  2. 当源节点和汇聚节点之间有一条增广路径时,将此路径添加到流中。
  3. 更新残差图。

    如果需要,我们也可以考虑反向路径,因为如果不考虑它们,我们可能永远找不到最大流。
    通过以下示例可以理解上述概念。

Ford-Fulkerson 示例

    所有边的流量在开始时为0。
在这里插入图片描述

  1. 选择从S到T的任意路径。在此步骤中,我们选择了路径 S-A-B-T。在这里插入图片描述
    三个边之中的最小容量为2(B-T)。基于此,更新每条路径的 流量/容量(flow/capacity)。
    在这里插入图片描述
  2. 选择另外一条路径 S-D-C-T。这些边的最小容量为3(S-D)。
    在这里插入图片描述
    根据此更新容量。
    在这里插入图片描述
  3. 现在,让我们考虑反向路径 B-D。选择路径 S-A-B-D-C-T。边之间的最小剩余容量为1(D-C)。(因为D-C容量为4,已有流量3,所以最多再加1流量,整个路径只能承载1的流量)
    在这里插入图片描述
    更新容量。
    在这里插入图片描述
    正向和反向路径的容量分别考虑。
  4. 将所有流量相加= 2 + 3 + 1 = 6,这是流量网络上的最大可能流量。
    从源节点S到汇聚节点T,流量共有3条路径:
    S-A-B-T,最大流量为2;
    S-D-C-T,最大流量为3;
    S-A-B-D-C-T,最大流量为1。
    所以最大流量是6。
    请注意,如果任何边的容量已满,则无法使用该路径承载更多流量。
C示例
/ Ford - Fulkerson algorith in C

#include <stdio.h>

#define A 0
#define B 1
#define C 2
#define MAX_NODES 1000
#define O 1000000000

int n;
int e;
int capacity[MAX_NODES][MAX_NODES];
int flow[MAX_NODES][MAX_NODES];
int color[MAX_NODES];
int pred[MAX_NODES];

int min(int x, int y) {
  return x < y ? x : y;
}

int head, tail;
int q[MAX_NODES + 2];

void enqueue(int x) {
  q[tail] = x;
  tail++;
  color[x] = B;
}

int dequeue() {
  int x = q[head];
  head++;
  color[x] = C;
  return x;
}

// Using BFS as a searching algorithm
int bfs(int start, int target) {
  int u, v;
  for (u = 0; u < n; u++) {
    color[u] = A;
  }
  head = tail = 0;
  enqueue(start);
  pred[start] = -1;
  while (head != tail) {
    u = dequeue();
    for (v = 0; v < n; v++) {
      if (color[v] == A && capacity[u][v] - flow[u][v] > 0) {
        enqueue(v);
        pred[v] = u;
      }
    }
  }
  return color[target] == C;
}

// Applying fordfulkerson algorithm
int fordFulkerson(int source, int sink) {
  int i, j, u;
  int max_flow = 0;
  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      flow[i][j] = 0;
    }
  }

  // Updating the residual values of edges
  while (bfs(source, sink)) {
    int increment = O;
    for (u = n - 1; pred[u] >= 0; u = pred[u]) {
      increment = min(increment, capacity[pred[u]][u] - flow[pred[u]][u]);
    }
    for (u = n - 1; pred[u] >= 0; u = pred[u]) {
      flow[pred[u]][u] += increment;
      flow[u][pred[u]] -= increment;
    }
    // Adding the path flows
    max_flow += increment;
  }
  return max_flow;
}

int main() {
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      capacity[i][j] = 0;
    }
  }
  n = 6;
  e = 7;

  capacity[0][1] = 8;
  capacity[0][4] = 3;
  capacity[1][2] = 9;
  capacity[2][4] = 7;
  capacity[2][5] = 2;
  capacity[3][5] = 5;
  capacity[4][2] = 7;
  capacity[4][3] = 4;

  int s = 0, t = 5;
  printf("Max Flow: %d\n", fordFulkerson(s, t));
}
Ford-Fulkerson 应用
  • 给水管网
  • 二部图匹配问题
  • 按需流通
参考文档

[1]Parewa Labs Pvt. Ltd.Ford-Fulkerson Algorithm[EB/OL].https://www.programiz.com/dsa/ford-fulkerson-algorithm,2020-01-01.

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值