如果权重为负,只要不存在循环,可以使用 Dijkstra 算法吗?

发布于 2024-12-06 15:19:45 字数 2024 浏览 1 评论 0原文

更新:我真的搞砸了原来的问题。我原来的标题是“为什么我们首先对非循环加权有向图最短路径问题进行拓扑排序?”但我的问题内容是关于Dijkstra算法的。希望自从我更改了标题后,问题就以对其他人有用的方式进行了更新。更新后的问题标题的答案是“”。

原问题

为什么我需要先进行拓扑排序? (请参阅此处的代码) 我不能只使用如下所示的 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 算法无法处理负循环(因为它会陷入无限循环),但如果没有负循环周期,为什么它会如图所示失败(并且首先需要拓扑排序)

更新:好的,我可以看到我已经搞砸了这个问题,所以我会尝试用一个修复它更新。感谢您花时间为我指出漏洞。我错误地认为 AcycloSP 在删除拓扑排序时成为 Dijkstra 算法,但事实并非如此案件。

然而,我关于 Dijkstra 算法(使用上面显示的版本)的问题仍然存在。为什么只要没有循环,即使有负权重也不能使用?这里有 Dijkstra 算法的 java 版本。我的例子与此非常相似(因为我是在这本书中了解到它的),但他的例子对于你们中的一些人来说可能更容易阅读。

Update: I really botched the original question. My original title was "Why do we first do a topological sort for acyclic weighted digraph shortest path problems?" but my question content was about Dijkstra's algorithm. Hopefully since I've changed the title, the question is updated in such a way that it is useful to someone else. The answer to the updated question title is "yes".

Original question:

Why do I need to do a topological sort first? (see code here) Can't I just use Dijkstra's algorithm shown below and avoid the topological sort altogether (little messy syntax-wise but you get the idea)

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

I can understand why Dijkstra's algorithm can't handle negative cycles (because it would get stuck in an infinite loop) but if there are no negative cycles, why does it fail as shown (and require the topological sort first)

Update: Ok, I can see that I've botched up this question so I will try to fix it up a bit with an update. Thanks for taking the time to point the hole's out for me. I mistakenly thought AcyclicSP becomes Dijkstra's algorithm when removing the topological sort which is not the case.

However, my question about Dijkstra's algorithm (using the version shown above) remains. Why can't it be used even if there is a negative weight so long as there are no cycles? There is a java version of Dijkstra's algorithm here. Mine is very similar to this (since this guy's book is where I learned about it) but his example is probably easier to read for some of you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

转角预定愛 2024-12-13 15:19:46

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

You don't make any topological sort in the original algorithm. But in the case of an a-cyclic graph, then you can decrees the running time to O(V) (while the original running time is O(|V|*log(|V|)).
The reason is that you sort in O(|V|) time, and then you can use that order, and don't need any heap (or priority queue). So the over all time decreases to O(|V|).

许一世地老天荒 2024-12-13 15:19:46

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

Dijkstra 算法不支持负路径成本,但确实处理循环。当它发现有一条更短的路径到达节点时,它会停止。循环路径不会更短并在那里停止(前提是成本非负)

Dijkstra's algorithm doesn't appear to require a topological sort. Perhaps doing so avoids a bug you have in your implementation.

Dijkstra's algorithm doesn't support negative path costs, but does handle looping cycles. It does this by stopping when it finds that there is a shorter path to a node. A looping path will not be shorter and there for stop (provided the cost is non-negative)

岁月打碎记忆 2024-12-13 15:19:46

无法将 Dijkstra 算法与负权重一起使用。
数百人尝试过,但没有人成功。

如果您有否定,请使用贝尔曼-福特算法。重量

It is not possible to use Dijkstra Algo with negative weights.
Hundreds have tried, no one was successfull.

Use Bellman-Ford Algo if you have neg. Weights

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文