了解福特-福克森算法

文章目录

          • 使用的术语
          • Ford-Fulkerson算法如何工作?
          • Ford-Fulkerson 示例
          • C示例
          • Ford-Fulkerson 应用
          • 参考文档

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

使用的术语

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

Ford-Fulkerson算法如何工作?

    该算法如下:

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

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

Ford-Fulkerson 示例

    所有边的流量在开始时为0。
了解福特-福克森算法_第2张图片

  1. 选择从S到T的任意路径。在此步骤中,我们选择了路径 S-A-B-T。了解福特-福克森算法_第3张图片
    三个边之中的最小容量为2(B-T)。基于此,更新每条路径的 流量/容量(flow/capacity)。
    了解福特-福克森算法_第4张图片
  2. 选择另外一条路径 S-D-C-T。这些边的最小容量为3(S-D)。
    了解福特-福克森算法_第5张图片
    根据此更新容量。
    了解福特-福克森算法_第6张图片
  3. 现在,让我们考虑反向路径 B-D。选择路径 S-A-B-D-C-T。边之间的最小剩余容量为1(D-C)。(因为D-C容量为4,已有流量3,所以最多再加1流量,整个路径只能承载1的流量)
    了解福特-福克森算法_第7张图片
    更新容量。
    了解福特-福克森算法_第8张图片
    正向和反向路径的容量分别考虑。
  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 

#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.

你可能感兴趣的:(数据结构与算法,福特-福克森算法,Ford-Fulkerson)