【问题标题】:Prim's algorithm with Fibonacci heap: why O(E + V*log(V))?Prim 的斐波那契堆算法:为什么是 O(E + V*log(V))?
【发布时间】:2018-12-18 06:09:38
【问题描述】:

我知道 Prim 的算法以及如何实现它。我也知道为什么它的时间复杂度是 O(E + V log(V))。

我们添加边 E 次(即 O(E))并选择最小 V 次(即 O(V*log(V))。但我不明白其中的一部分:为什么 V 次? ! 我知道一棵树有 V-1 条边,但如果最重的边必须在 MST 中,我们必须选择最少 E 次,而不是 V 次。

例如:一个完整​​的图,每条边的权重为 1,除了一个顶点,所有与其相连的边的权重为 10^18。

【问题讨论】:

  • 您将顶点放入队列中,而不是边。见en.wikipedia.org/wiki/Prim%27s_algorithm
  • 但那是不可能的! c++ priority_queue 没有随机访问或任何类型的迭代器。
  • 您问的是使用斐波那契堆,而不是 C++ 优先级队列。获得 O(E + V log V) 依赖于 C++ priority_queue 不提供的恒定摊销时间 reduction_key 操作。

标签: algorithm graph-theory minimum-spanning-tree disjoint-sets fibonacci-heap


【解决方案1】:

您想使用初始图中的边连接 V 个顶点,形成一棵树。您可以从任何节点开始,比如说 v。然后将可以从 v 到达的所有顶点添加到队列中,并以连接它的边的成本为代价。你去成本最低的那个。现在你做同样的事情。如果您想将已经在队列中的顶点 u 放入队列中,则必须检查其边缘的工资。如果新的较小,则取出旧的并插入新的,如果没有,则跳过它。此外,如果您已经将节点 u 连接到您的树,您也可以跳过它。所以你的队列中最多有 V 个顶点,使得时间复杂度 O (E + V log V) (E - 因为你必须检查每个顶点的所有边)

编辑:更具体地说,当您将顶点 u 再次添加到队列中时,您可以删除前一个,或者只是更改它的成本。如果您使用斐波那契堆,另一件事应该会更快。删除将花费您 O(E log V) 而不是 O(E + VlogV)

【讨论】:

  • 您在询问是否将顶点保留在优先级队列中。制作一个节点数组并给每个节点一个 id。然后在你的队列中保留对 .
猜你喜欢
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 2012-12-16
  • 2010-11-24
  • 1970-01-01
  • 2013-03-31
相关资源
最近更新 更多