我正在处理来自UVa问题集的this graph problem。这是一个单源最短路径问题,没有负边缘权重。根据我的收集,具有最佳大O运行时间的算法是Dijkstra,其中Fibonacci堆作为优先级队列,尽管实际上二进制堆更容易实现并且也很好用。
然而,似乎即使是二进制堆也需要相当长的时间才能滚动,并且在竞争时间内是有限的。我知道STL提供了一些堆算法和优先级队列,但它们似乎没有提供Dijkstra所需的减少键功能。或者我错了吗?
似乎另一种可能性就是不使用Dijkstra。 This forum thread有人声称他们通过广度优先搜索/ Bellman-Ford解决了上述问题,这些搜索更容易编码。 (编辑:OTOH,Dijkstra的优先级队列的未排序数组超时。)BFS / Bellman-Ford工作让我感到惊讶,因为我认为输入的大小非常大。我想不同的问题需要不同复杂程度的解决方案,但我的问题是,在竞争中我需要多久使用一次Dijkstra?我应该在更简单但更慢的算法上练习更多吗?
答案 0 :(得分:4)
如果你能提出一个好的最佳优先启发式,我会尝试使用A*
答案 1 :(得分:2)
根据我自己的经验,我从来不需要在编程竞赛中用堆来实现Dijkstra算法。您可以使用速度较慢但效率较高的算法在大多数情况下逃脱。您可以使用最好的Dijkstra实现来解决需要不同/更简单算法的问题,但这种情况很少见。
答案 2 :(得分:1)
您可以使用堆叠/优先级队列来实现Dijkstra,而不使用减少键(我认为)O((E + V)log V)。如果要减少密钥,只需将新条目添加到优先级队列(将旧条目保留在队列中)并使用距离更新阵列。当您从队列中取出最小元素时,首先检查它是否等于您的距离数组,如果不是那么它是您想要减少的键,所以只需忽略它。
答案 3 :(得分:0)
Boost Graph Library似乎有Dijkstra和Bellman-Ford的实施。
答案 4 :(得分:0)
Dijkstra和一个简单的优先级队列即使对于大型数据集也应该做得很好。如果你正在练习,你也可以尝试使用二进制堆并比较性能。当然,我认为做一个斐波纳契堆有点边缘,并会选择先练习其他数据结构和算法。
有趣的是,使用优先级队列等同于广度优先搜索,首先探索当前最佳解决方案。