更新:我真的搞砸了原来的问题。我的原始标题是“为什么我们首先对非循环加权有向图最短路径问题进行拓扑排序?”但我的问题内容是关于Dijkstra的算法。希望自从我更改了标题后,问题会以对其他人有用的方式更新。更新的问题标题的答案是“是”。
原始问题:
为什么我需要先进行拓扑排序? (see code here)我不能只使用下面显示的Dijkstra算法并完全避免拓扑排序(语法方面有点混乱,但你明白了)
MinIndexedPriorityQueue waitingEdges = new MinIndexedPriorityQueue
Graph g //some weighted directed graph
double[] distTo = new double[g.vertexCount]
Edge[] edgeTo = new Edge[g.vertexCount]
int source = //init to some value
void minPathInit()
init distTo to double.MAX_VALUE
//init first node
distTo [source] = 0
visit(source)
while waitingEdges.count>0
int vertex = waitingEdges.dequeue()
relax(vertex )
void relax(v) //note that visit has been renamed to relax
for each edge in graph.getEdgesFrom(v)
int to= edge.to
if edge.weight + distTo [edge.from]< distTo [to]
distTo[to] = edge.weight + distTo [edge.from]
edgeTo[to] = edge
if waitingEdges.contains(to)
waitingEdges.change(to, distTo[to] )
else
waitingEdges.enqueue(to, distTo[to] )
//after everything is initialized
getPathTo(v)
if not hasBeenVisited[v]
return null
Stack path = new Stack
while edgeTo[v] != source
path.push(edgeTo[v])
v = edgeTo[v].from
return path
我可以理解为什么Dijkstra的算法不能处理负循环(因为它会陷入无限循环)但是如果没有负循环,为什么它会如图所示失败(并且首先需要拓扑排序)
更新:好的,我可以看到我已经搞砸了这个问题所以我会尝试通过更新来修复它。感谢您花时间为我指出漏洞。我错误地认为AcyclicSP在删除拓扑排序时变成了Dijkstra的算法,而不是这种情况。
然而,我关于Dijkstra算法的问题(使用上面显示的版本)仍然存在。只要没有循环,为什么即使负重也不能使用?有Dijkstra's algorithm here的java版本。我与此非常相似(因为这本书是我了解它的地方),但他的例子对你们中的一些人来说可能更容易阅读。
答案 0 :(得分:3)
您不在原始算法中进行任何拓扑排序。但是在a-cyclic图的情况下,则可以将运行时间设为O(V)(原始运行时间为O(| V | * log(| V |))。 原因是您在O(| V |)时间内排序,然后您可以使用该顺序,并且不需要任何堆(或优先级队列)。所以总是减少到O(| V |)。
答案 1 :(得分:2)
Dijkstra的算法似乎不需要拓扑排序。也许这样做可以避免您在实现中遇到的错误。
Dijkstra的算法不支持负路径成本,但确实处理循环周期。它通过在发现节点的路径较短时停止来完成此操作。循环路径不会更短并且停止(假设成本是非负的)
答案 2 :(得分:1)
无法使用负重的Dijkstra Algo。 数百人尝试过,没有人成功。
如果你有否,请使用Bellman-Ford算法。权重