代码之家  ›  专栏  ›  技术社区  ›  int3

对于编程竞赛,最好的单源最短路径算法是什么?

  •  1
  • int3  · 技术社区  · 16 年前

    我正在努力 this graph problem 来自uva问题集。这是一个没有负边权的单源最短路径问题。根据我收集的信息,对于这些问题,运行时间最好的big-o算法是dijkstra,它以fibonacci堆作为优先级队列,尽管实际上,二进制堆更容易实现,而且工作也很好。

    然而,似乎即使是二进制堆也需要相当长的时间滚动,而且在竞争中时间是有限的。我知道STL提供了一些堆算法和优先级队列,但它们似乎没有提供Dijkstra需要的reduce-key函数。还是我错了?

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

    5 回复  |  直到 10 年前
        1
  •  2
  •   leiz    16 年前

    根据我自己的经验,我从不需要在编程比赛中用堆实现Dijkstra算法。你可以利用一个速度较慢但效率足够高的算法,在大多数情况下逃走。您可以使用一个最好的dijkstra实现来解决一个需要不同/更简单算法的问题,但这种情况很少发生。

        2
  •  4
  •   Ben S    16 年前

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

        3
  •  1
  •   theycallhimtom    16 年前

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

        4
  •  0
  •   erenon    16 年前

    这个 Boost Graph Library 似乎对Dijkstra和BellmanFord都有实现。

        5
  •  0
  •   Mike Ashley    16 年前

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

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