【问题标题】:What is the best single-source shortest path algorithm for programming contests?编程竞赛的最佳单源最短路径算法是什么?
【发布时间】:2026-01-10 18:30:01
【问题描述】:

我正在研究 UVa 问题集中的this graph problem。这是一个没有负边权重的单源最短路径问题。从我收集到的信息来看,对于此类问题具有最佳 big-O 运行时间的算法是 Dijkstra,它使用 Fibonacci 堆作为优先级队列,尽管实际上二进制堆更容易实现并且效果也很好。

然而,看起来即使是二叉堆也需要相当长的时间才能滚动,而且在竞争中时间是有限的。我知道 STL 提供了一些堆算法和优先级队列,但它们似乎没有提供 Dijkstra 需要的减少键功能。还是我错了?

似乎另一种可能性是根本不使用 Dijkstra 的。 This forum thread 有人声称他们通过广度优先搜索 / Bellman-Ford 解决了上述问题,这更容易编码。 (编辑:OTOH,Dijkstra 的优先级队列的未排序数组超时。)BFS/Bellman-Ford 的工作让我有点惊讶,因为我认为输入大小非常大。我想不同的问题需要不同复杂性的解决方案,但我的问题是,我需要多久在这样的比赛中使用 Dijkstra 的?我应该更多地练习更简单但更慢的算法吗?

【问题讨论】:

    标签: c++ algorithm graph


    【解决方案1】:

    如果你能想出一个好的最好的启发式方法,我会尝试使用A*

    【讨论】:

      【解决方案2】:

      根据我自己的经验,我从来不需要在编程比赛中用堆实现 Dijkstra 算法。使用较慢但足够高效的算法,您可以在大多数情况下摆脱困境。您可能会使用最好的 Dijkstra 实现来解决需要不同/更简单算法的问题,但这种情况很少见。

      【讨论】:

        【解决方案3】:

        您可以使用堆/优先级队列实现 Dijkstra,而无需在(我认为)O((E+V)log V) 中使用减少键。如果您想减少键,只需将新条目添加到您的优先级队列中(将旧条目留在队列中)并使用距离更新您的数组。当您从队列中取出最小元素时,首先检查它是否等于您的距离数组,如果不是,那么它是您想要减少的键,所以忽略它。

        【讨论】:

          【解决方案4】:

          Boost Graph Library 似乎对 Dijkstra 和 Bellman-Ford 都有实现。

          【讨论】:

            【解决方案5】:

            Dijkstra 和一个简单的优先级队列即使对于大型数据集也应该很好。如果您正在练习,您也可以尝试使用二进制堆并比较性能。当然,我认为做斐波那​​契堆有点边缘,我会选择先练习其他数据结构和算法。

            有趣的是,使用优先级队列等同于广度优先搜索,具有先探索当前最佳解决方案的启发式算法。

            【讨论】:

              最近更新 更多