当前位置:   article > 正文

图论学习 c++Ford-Fulkerson 方法

图论学习 c++Ford-Fulkerson 方法

Ford-Fulkerson算法是用于求解最大流问题的一种经典算法。其核心思想是通过不断寻找增广路径来增加流量,直到找不到增广路径为止。每次找到一条增广路径,就增加相应的流量,更新残余网络。简单来说就是Ford-Fulkerson算法的工作过程,即不断寻找增广路径并增加流量,直到无法找到增广路径为止。

算法步骤

  1. 初始化: 将所有边的流量初始化为0。
  2. 寻找增广路径: 使用深度优先搜索(DFS)或广度优先搜索(BFS)在残余网络中寻找从源点到汇点的增广路径。
  3. 增广路径上增加流量: 在找到的增广路径上增加可以增加的最小流量。
  4. 更新残余网络: 根据增广路径上的流量调整残余网络。
  5. 重复步骤2-4,直到找不到增广路径为止。

以一个简单的例子来演示Ford-Fulkerson算法的执行过程。

假设有一个流网络如下:

  1. 源点 (S)
  2. / \
  3. 10 5
  4. / \
  5. A B
  6. \ /
  7. 5 10
  8. \ /
  9. C
  10. |
  11. 10
  12. |
  13. 汇点 (T)

其中每条边的数字表示容量。

步骤1:初始化

  • 所有边的流量初始化为0。

步骤2:寻找增广路径

  • 使用DFS或BFS从源点S寻找增广路径。假设我们使用DFS找到路径S -> A -> C -> T,路径上的容量为10,最小容量为5。

步骤3:增广路径上增加流量

  • 增加流量5。路径S -> A -> C -> T上各边的流量增加5。
  • 更新后的流量:
    • S -> A 流量为5,剩余容量为5。
    • A -> C 流量为5,剩余容量为0。
    • C -> T 流量为5,剩余容量为5。

步骤4:更新残余网络

  • 根据增广路径上的流量调整残余网络。增加逆向边用于表示可以回退的流量。
    • 增加逆向边A -> S,容量为5,流量为0。
    • 增加逆向边C -> A,容量为5,流量为0。
    • 增加逆向边T -> C,容量为5,流量为0。

步骤2:寻找增广路径(继续)

  • 继续寻找另一条增广路径。假设找到路径S -> B -> C -> T,路径上的容量为10,最小容量为5。

步骤3:增广路径上增加流量

  • 增加流量5。路径S -> B -> C -> T上各边的流量增加5。
  • 更新后的流量:
    • S -> B 流量为5,剩余容量为0。
    • B -> C 流量为5,剩余容量为5。
    • C -> T 流量为10,剩余容量为0。

步骤4:更新残余网络

  • 根据增广路径上的流量调整残余网络。增加逆向边用于表示可以回退的流量。
    • 增加逆向边B -> S,容量为5,流量为0。
    • 增加逆向边C -> B,容量为5,流量为0。
    • 增加逆向边T -> C,容量为5,流量为0。

步骤2:寻找增广路径(结束)

  • 继续寻找增广路径,发现没有增广路径了。

结果

  • 最大流量为10。
  1. #include <iostream> // 包含输入输出流的头文件
  2. #include <vector> // 包含向量容器的头文件
  3. #include <queue> // 包含队列容器的头文件
  4. #include <climits> // 包含INT_MAX定义的头文件
  5. #include <cstring> // 包含memset函数的头文件
  6. using namespace std; // 使用标准命名空间
  7. class FordFulkerson {
  8. int V; // 顶点数量
  9. vector<vector<int>> capacity; // 容量矩阵
  10. vector<vector<int>> adj; // 邻接表
  11. // 广度优先搜索(BFS)函数,用于在残余网络中寻找增广路径
  12. bool bfs(vector<int>& parent, int s, int t) {
  13. vector<bool> visited(V, false); // 访问标记数组,初始化为未访问
  14. queue<int> q; // BFS队列
  15. q.push(s); // 源点入队
  16. visited[s] = true; // 标记源点为已访问
  17. parent[s] = -1; // 源点没有父节点
  18. while (!q.empty()) { // 当队列不为空时
  19. int u = q.front(); // 取出队首元素
  20. q.pop(); // 队首元素出队
  21. for (int v : adj[u]) { // 遍历邻接表中的所有邻接节点
  22. if (!visited[v] && capacity[u][v] > 0) { // 如果节点未访问且有剩余容量
  23. if (v == t) { // 如果找到汇点
  24. parent[v] = u; // 记录父节点
  25. return true; // 返回找到增广路径
  26. }
  27. q.push(v); // 将节点入队
  28. parent[v] = u; // 记录父节点
  29. visited[v] = true; // 标记节点为已访问
  30. }
  31. }
  32. }
  33. return false; // 如果没有找到增广路径,返回false
  34. }
  35. public:
  36. // 构造函数,初始化顶点数量、容量矩阵和邻接表
  37. FordFulkerson(int V) : V(V), capacity(V, vector<int>(V, 0)), adj(V) {}
  38. // 添加边及其容量
  39. void addEdge(int u, int v, int cap) {
  40. capacity[u][v] = cap; // 设置容量
  41. adj[u].push_back(v); // 添加邻接点
  42. adj[v].push_back(u); // 添加反向边的邻接点
  43. }
  44. // 计算最大流量
  45. int maxFlow(int s, int t) {
  46. int max_flow = 0; // 初始化最大流量为0
  47. vector<int> parent(V); // 用于记录增广路径中的父节点
  48. while (bfs(parent, s, t)) { // 当找到增广路径时
  49. int path_flow = INT_MAX; // 初始化路径流量为无穷大
  50. // 计算增广路径中的最小流量
  51. for (int v = t; v != s; v = parent[v]) {
  52. int u = parent[v];
  53. path_flow = min(path_flow, capacity[u][v]);
  54. }
  55. // 更新残余网络中的容量
  56. for (int v = t; v != s; v = parent[v]) {
  57. int u = parent[v];
  58. capacity[u][v] -= path_flow;
  59. capacity[v][u] += path_flow;
  60. }
  61. // 增加总流量
  62. max_flow += path_flow;
  63. }
  64. return max_flow; // 返回最大流量
  65. }
  66. };
  67. int main() {
  68. int V = 6; // 顶点数量 (包括源点和汇点)
  69. FordFulkerson graph(V); // 创建一个FordFulkerson对象
  70. // 添加边和对应的容量
  71. graph.addEdge(0, 1, 10); // S -> A 容量 10
  72. graph.addEdge(0, 2, 5); // S -> B 容量 5
  73. graph.addEdge(1, 3, 5); // A -> C 容量 5
  74. graph.addEdge(2, 3, 10); // B -> C 容量 10
  75. graph.addEdge(3, 5, 10); // C -> T 容量 10
  76. int source = 0; // 源点 S
  77. int sink = 5; // 汇点 T
  78. // 计算并输出最大流量
  79. cout << "最大流量: " << graph.maxFlow(source, sink) << endl;
  80. return 0;
  81. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/812759
推荐阅读
相关标签
  

闽ICP备14008679号