【问题标题】:Why must back-edges be taken into account in Edmonds-Karp Maximum Flow?为什么在 Edmonds-Karp 最大流量中必须考虑后沿?
【发布时间】:2016-08-09 06:50:34
【问题描述】:

我试图在 C++ 中实现 Edmonds-Karp 以获得最大流量,但我的编写方式略有不同:

  1. 我没有遍历残差图中的所有边,而是使用邻接表仅遍历原始图中存在的边。
  2. 在使用最小流量更新残差图时,我没有更新任何后边。

有趣的是,当我运行我的代码时,它给了我正确的结果。所以我去了Wikipedia's example,它专门展示了如何使用后端。当我将此图表输入到我的代码中时,我又得到了正确答案。 我还检查了结果流矩阵,它与维基百科的相同。

有人可以解释为什么我们必须添加和更新后端,并举个例子说明它们很重要吗?

Here 是我编写的代码(已更新为包含后端):

【问题讨论】:

  • 只是为了确保理解好,是不是说当你以相反的方式取一个圆弧时,你并没有更新这个圆弧上的流量值?
  • @DamienProt 我有这样的想法,我不遍历残差图,而是只遍历原始邻接列表。所以我从来没有访问过任何后端,也没有看到任何更新的意义。

标签: c++ algorithm graph ford-fulkerson edmonds-karp


【解决方案1】:

考虑以下流网络

假设第一个流是s → u → v → t。 (如果你反对 Edmonds-Karp 的 BFS 永远不会选择这个,那么在 sv 之间以及 u 和 t)。

没有逆流u → v,不可能得到20的最优流。

【讨论】:

  • BFS 首先发现最短路径(边数)。它会先抓取两条10条流路,不考虑1条权重边。我刚刚用你的图表运行了我的代码,最大流量确实是 20。
  • @prakharsingh95 :我完全同意 Ami Tavory 的回答,忘记后边缘是没有意义的。
  • 抱歉,我在手机上,不知怎的错过了它。确实你是对的。事实上,@ead 给出了同样的例子。据我了解,这意味着当路径较长且净流量大于与它们共享边的短路径时,有必要添加后边。
  • @DamienProt 是的,后边缘很重要。我就是不知道为什么!
  • 我可能疯了,但是我们不能将任何一个传入和一个传出的节点系列折叠成一个具有原始边集最小值的节点吗?例如:A - (5) -> B - (4) -> C - (5) -> D 可以简化为 A - (4) -> D
【解决方案2】:

试试下面的案例:

int main() {
    Digraph<int> g(8);
    g.addEdge(0,1,1);
    g.addEdge(1,2,1);
    g.addEdge(2,4,1);
    g.addEdge(0,3,1);
    g.addEdge(3,4,1);
    g.addEdge(4,7,1);
    g.addEdge(3,5,1);
    g.addEdge(5,6,1);
    g.addEdge(6,7,1);

    cout<<g.maxFlowEdmondsKarp(0,7);

    return 0;
}

可视化:

您的程序首先采用最短路径0-3-4-7,然后没有机会找到0-1-2-4-70-3-5-6-7。你得到 1 但 2 是正确的答案。

您是否已插入后边缘,然后您会找到以下路径:

  1. 0-3-4-7
  2. 0-1-2-4-3(back-edge!)-5-6-7,获取最大流量2。

【讨论】:

    猜你喜欢
    • 2012-11-20
    • 1970-01-01
    • 2010-12-30
    • 2021-06-29
    • 2020-08-03
    • 2012-02-03
    • 2014-11-15
    • 2017-02-21
    • 1970-01-01
    相关资源
    最近更新 更多