使用 Dijkstra 找到最小生成树?
Dijkstra's is typically used to find the shortest distance between two nodes in a graph. Can it be used to find a minimum spanning tree? If so, how?
Edit: This isn't homework, but I am trying to understand a question on an old practice exam.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
答案是否定的。要了解原因,让我们首先像这样阐明问题:
问:对于仅具有非负边权重的连通、无向、带权图 G = (V, E, w),前驱子图是否由Dijkstra算法形成G的最小生成树?
(请注意,无向图是一类特殊的有向图,因此在无向图上使用 Dijkstra 算法是完全可以的。此外,MST 仅针对连通的无向图定义,如果图未加权,则 MST 是微不足道的,因此我们必须将我们的查询限制在这些图上。)
答:Dijkstra 算法在每一步都会贪婪地选择最接近某个源顶点的下一条边。它会执行此操作,直到 s 连接到图中的所有其他顶点。显然,生成的前驱子图是 G 的生成树,但是边权重之和是否最小化了?
Prim 算法已知可以生成最小生成树,与 Dijkstra 算法高度相似,但在每个阶段它都会贪婪地选择最接近当前工作中任何顶点的下一条边该阶段的 MST。让我们用这个观察来产生一个反例。
反例:考虑无向图
G = (V, E, w)
,其中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。
The answer is no. To see why, let's first articulate the question like so:
Q: For a connected, undirected, weighted graph
G = (V, E, w)
with only nonnegative edge weights, does the predecessor subgraph produced by Dijkstra's Algorithm form a minimum spanning tree of G?(Note that undirected graphs are a special class of directed graphs, so it is perfectly ok to use Dijkstra's Algorithm on undirected graphs. Furthermore, MST's are defined only for connected, undirected graphs, and are trivial if the graph is not weighted, so we must restrict our inquiry to these graphs.)
A: Dijkstra's Algorithm at every step greedily selects the next edge that is closest to some source vertex s. It does this until s is connected to every other vertex in the graph. Clearly, the predecessor subgraph that is produced is a spanning tree of
G
, but is the sum of edge weights minimized?Prim's Algorithm, which is known to produce a minimum spanning tree, is highly similar to Dijkstra's Algorithm, but at each stage it greedily selects the next edge that is closest to any vertex currently in the working MST at that stage. Let's use this observation to produce a counterexample.
Counterexample: Consider the undirected graph
G = (V, E, w)
whereV = { 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 )
}
Take
a
as the source vertex.Dijkstra's Algorithm takes edges
{ (a,b), (a,c), (a,d) }
.Thus, the total weight of this spanning tree is 5 + 5 + 5 = 15.
Prim's Algorithm takes edges
{ (a,d), (b,d), (c,d) }
.Thus, the total weight of this spanning tree is 5 + 1 + 1 = 7.
严格来说,答案是否定的。 Dijkstra 算法找到图上 2 个顶点之间的最短路径。然而,对算法进行很小的改变就会产生另一种能够有效生成 MST 的算法。
算法设计手册是我发现回答此类问题的最好的书一。
Strictly, the answer is no. Dijkstra's algorithm finds the shortest path between 2 vertices on a graph. However, a very small change to the algorithm produces another algorithm which does efficiently produce an MST.
The Algorithm Design Manual is the best book I've found to answer questions like this one.
Prim 算法 使用与 Dijkstra 算法相同的基本原理。
Prim's algorithm uses the same underlying principle as Dijkstra's algorithm.
我会坚持使用 Prim 或 Kruskal 等贪婪算法。我担心 Djikstra 不会这样做,只是因为它最大限度地减少了节点对之间的成本,而不是整个树的成本。
I'd keep to a greedy algorithm such as Prim's or Kruskal's. I fear Djikstra's won't do, simply because it minimizes the cost between pairs of nodes, not for the whole tree.
当然,可以使用 Dijkstra 进行最小生成树:
这是使用 Dijkstra 进行生成树的示例:
您可以在《算法基础》一书第 4 章第 2 节中找到进一步的解释。
希望这会有所帮助
Of course, It's possible to use Dijkstra for minimum spanning tree:
Here is an example of using Dijkstra for spanning tree:
You can find further explanation in Foundations of Algorithms book, chapter 4, section 2.
Hope this help