只要没有循环,如果有负重,你能使用Dijkstra的算法吗?

时间:2011-09-26 09:06:09

标签: algorithm data-structures graph graph-theory

更新:我真的搞砸了原来的问题。我的原始标题是“为什么我们首先对非循环加权有向图最短路径问题进行拓扑排序?”但我的问题内容是关于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版本。我与此非常相似(因为这本书是我了解它的地方),但他的例子对你们中的一些人来说可能更容易阅读。

3 个答案:

答案 0 :(得分:3)

您不在原始算法中进行任何拓扑排序。但是在a-cyclic图的情况下,则可以将运行时间设为O(V)(原始运行时间为O(| V | * log(| V |))。 原因是您在O(| V |)时间内排序,然后您可以使用该顺序,并且不需要任何堆(或优先级队列)。所以总是减少到O(| V |)。

答案 1 :(得分:2)

Dijkstra的算法似乎不需要拓扑排序。也许这样做可以避免您在实现中遇到的错误。

Dijkstra的算法不支持负路径成本,但确实处理循环周期。它通过在发现节点的路径较短时停止来完成此操作。循环路径不会更短并且停止(假设成本是非负的)

答案 2 :(得分:1)

无法使用负重的Dijkstra Algo。 数百人尝试过,没有人成功。

如果你有否,请使用Bellman-Ford算法。权重