编程竞赛的最佳单源最短路径算法是啥?

Posted

技术标签:

【中文标题】编程竞赛的最佳单源最短路径算法是啥?【英文标题】:What is the best single-source shortest path algorithm for programming contests?编程竞赛的最佳单源最短路径算法是什么? 【发布时间】:2009-12-07 21:02:06 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

以上是关于编程竞赛的最佳单源最短路径算法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

贪心算法—单源最短路径

挑战程序设计竞赛(算法和数据结构)——13.3单源最短路径(dijkstra算法)的JAVA实现

图文解析 Dijkstra单源最短路径算法

单源最短路径

单源最短路径

数据结构—— 图:最短路径问题