在线性时间内验证从每个节点到汇聚节点的最小成本

Verifying the minimum cost from each node to a sink node in linear time

问题陈述:

G = (V,E) 成为成本为 ce[=65= 的有向图] ∈ ℝ 在每条边上 eEG中没有负循环。假设有一个sink节点tV,对于每个节点vV,有一个标签dv∈ℝ。

给出一个算法,在线性时间内,对于每个 vV, dv是从v到sink节点t[的最小代价路径的代价=65=].

尝试:

我发现最大的挑战是线性时间限制。这里考虑的最相关的算法是Bellman-Ford算法,但是运行时间为O(|V|·|E|)太慢,所以需要针对这个问题进行修改。

我也观察了一下:

如果,例如,(u,v)E 并且 c(u,v) = 1,并且 du = 3和dv = 5,则标签dv错了。这是因为从 vu 的成本为 1,从 ut 在最小成本为 3 的情况下总成本为 4 比假定的从 vt[=65 的最小成本要短=] 由 dv 给出,即 5.

我不确定我是否可以使用这种洞察力来生成线性算法,但这是迄今为止我得到的最远的算法。

是的,您的洞察力是高效算法的重要组成部分。给定一个节点 u——不同于 t——它的出边 e=(u,v)应该满足这个条件:

ce + vd ≥ ud

除此之外,这些边中至少有一条 e 应该在节点的最小成本路径中:

ce + vd = ud

以上两个条件可以浓缩为如下,其中Eu是起源于[=38的边的集合=]u:

min(ce + vd) = ud 对于 e=(u,v) ∈ Eu

最后,汇点t的最小成本路径应该为零:

dt = 0

因此,可以设计一种算法,仅访问所有节点及其出边一次,以验证这些条件。

时间复杂度

如果你有用邻接表表示的图,那么这确实可以在 O(|V| + |E|) 时间内完成。如果图形是连通的,那么这可以归结为 O(|E|).

伪代码

function verify(nodes, sink):
    if sink.label != 0:
        return False
    for node in nodes:
        if node != sink:
            cost = infinity
            for e in node.outgoingEdges:
                cost = min(cost, e.target.label + e.cost) 
            if node.label != cost:
                return False
    return True

有关 Python 中的实现,请参阅 this repl.it