【问题标题】:Use Dijkstra's to find a Minimum Spanning Tree?使用 Dijkstra 找到最小生成树?
【发布时间】:2009-12-15 18:08:47
【问题描述】:

Dijkstra's 通常用于查找图中两个节点之间的最短距离。可以用它找到最小的spanning tree吗?如果有,怎么做?

编辑:这不是家庭作业,但我正在尝试理解旧练习考试中的一个问题。

【问题讨论】:

  • 你使用 Greedy 来查找 MST。对于最短路径,您使用最优性原理(最优子结构),动态规划。在 DP 中,您会发现图表自下而上,并且每个阶段都是最优的。对于贪心,你只需选择一个贪心标准,你就会找到 MST。如果你了解 Greedy 和 DP,你真的能感受到其中的不同。 MST 不应包含 Cycle。最短路径可以包含循环。尝试了解如何找到它们的基本理论,您将更好地理解差异。最短路径是 NP 完备的,而 MST 不是。如果您可以使用 MST 来解决最短路径。那么 P=NP。
  • 此评论不正确,因为最短路径肯定不是 NP 完整的。证明是 Dijkstra 的算法是多项式的。不要使用严格的 Dijkstra 算法和基于到一个节点的距离的优先级队列,而是使用基于边权重的优先级队列。在每一步添加权重最小且不创建循环的边界边。

标签: algorithm language-agnostic graph-theory dijkstra minimum-spanning-tree


【解决方案1】:

答案是否定的。要了解原因,让我们先这样表述问题:

问:对于只有非负边权重的连通无向加权图G = (V, E, w),Dijkstra 算法生成的前驱子图是否形成 G 的最小生成树?

(请注意,无向图是一类特殊的有向图,因此在无向图上使用 Dijkstra 算法是完全可以的。此外,MST 仅用于连接的无向图,并且如果图没有加权,则它是微不足道的,所以我们必须将我们的查询限制在这些图表上。)

答:Dijkstra 算法在每一步都贪婪地选择最接近某个 源顶点 s 的下一条边。它这样做直到 s 连接到图中的每个其他顶点。很明显,生成的前驱子图是G的生成树,但是边权重之和最小化了吗?

Prim 算法,已知会产生最小生成树,与 Dijkstra 算法高度相似,但在每个阶段它都会贪婪地选择最接近 当前任何顶点的下一条边在那个阶段的工作 MST 中。让我们用这个观察来产生一个反例。

反例:考虑无向图G = (V, E, w) where

V = { a, b, c, d }

E = { (a,b), (a,c), (a,d), (b,d), (c,d) }

w = { ( (a,b) , 5 ) ( (a,c) , 5 ) ( (a,d) , 5 ) ( (b,d) , 1 ) ( (c,d) , 1 ) }

a为源顶点。

Dijkstra 算法取得优势{ (a,b), (a,c), (a,d) }
因此,这棵生成树的总权重为5 + 5 + 5 = 15

Prim 的算法占据优势 { (a,d), (b,d), (c,d) }
因此,这棵生成树的总权重为5 + 1 + 1 = 7

【讨论】:

  • 这是一个绝妙的反例。来自d vertex 的 Dijkstra 仍会产生 MST。
  • 这一定是我在 Stack Overflow 上看到的更好的答案之一!用简单的例子清楚地解释一个复杂的问题。
  • 很好的例子。因此,可以得出结论,在 Djikstra 中,我们倾向于找到一条生成树的路径,它可以最大限度地减少从源到每个其他目的地的成本,而 MST 只是倾向于使权重的总和最小,它并不关心使每个源到每个其他节点的权重最小
【解决方案2】:

严格来说,答案是否定的。 Dijkstra 算法在图上找到 2 个顶点之间的最短路径。但是,对算法进行非常小的更改会生成另一种算法,该算法确实可以有效地生成 MST。

The Algorithm Design Manual 是我找到的最能回答此类问题的书。

【讨论】:

    【解决方案3】:

    Prim's algorithm 使用与 Dijkstra 算法相同的基本原理。

    【讨论】:

    • 优秀。简洁而优雅。
    【解决方案4】:

    我会坚持使用 Prim 或 Kruskal 等贪婪算法。我担心 Djikstra 不会这样做,仅仅是因为它最小化了节点对之间的成本,而不是整个树。

    【讨论】:

      【解决方案5】:

      当然,可以使用 Dijkstra 作为最小生成树:

      dijsktra(s):
      dist[s] = 0;
      while (some vertices are unmarked) {
          v = unmarked vertex with 
          smallest dist;
          Mark v; // v leaves “table”
          for (each w adj to v) {
              dist[w] = min[ dist[w], dist[v] + c(v,w) ];
          }
      }
      

      这是一个使用 Dijkstra 生成树的示例:

      您可以在《算法基础》一书第 4 章第 2 节中找到进一步的解释。

      希望有帮助

      【讨论】:

      • 这包含实现的伪代码。请添加解释。
      • 树 (v1, v5), (v5, v4), (v1, v3), (v3, v2) 是不是比图片中显示的更小?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-30
      相关资源
      最近更新 更多