【发布时间】:2016-06-17 00:02:18
【问题描述】:
我想知道使用动态规划在线性时间内计算顶点 s 和图中每个其他顶点之间最短路径长度的最佳方法。
该图是加权 DAG。
【问题讨论】:
标签: dynamic-programming graph-algorithm directed-acyclic-graphs
我想知道使用动态规划在线性时间内计算顶点 s 和图中每个其他顶点之间最短路径长度的最佳方法。
该图是加权 DAG。
【问题讨论】:
标签: dynamic-programming graph-algorithm directed-acyclic-graphs
您所希望的是一种与边和顶点数量呈线性关系的算法,即O(|E| + |V|),它在存在负权重的情况下也能正常工作。
这是通过首先计算拓扑顺序,然后按照该拓扑顺序给出的顺序“探索”图形来完成的。
一些符号:让我们称d'(s,v) 为从s 到v 的最短距离和d(u,v) 从u 到v 的弧的长度/重量(如果存在)。
那么,对于当前正在访问的节点 v,从 s 到 v 的最短路径是 v 的每个相邻 u 中的最小值 d'(s,u)+d(u,v)。
原则上,这与 Dijkstra 算法非常相似,只是我们已经知道遍历顶点的顺序。
拓扑排序确保v的所有近邻都已经被访问过,不会再次更新。因此,每当访问一个节点时,它所分配的距离就是从s 到v 的正确最短路径。因此,您最终会得到每个 v 的最短 s-v-path。
完整的描述和实现可以在here找到,它链接到these lecture notes。我不确定这个 DAG 算法的算法思想最初是在哪里发表的。
该算法适用于 DAG,即使存在负权重/距离。
虽然这个算法的典型实现很可能不会显式地使用动态规划来完成,但它仍然可以被解释为这样,因为找到到节点 v 的最短路径的问题是使用到节点的最短路径来计算的。 v 的邻居。
有关此类算法是否/如何算作动态编程的进一步讨论,请让我将您推荐给this question。
【讨论】:
您正在寻找的可能是 Bellman-Ford 算法,它的时间复杂度为 O(|V||E|)(不是真正的线性)。
不确定是否有一些机智的动态编程方法可以改进这一点。
【讨论】:
正如 hauron 所说,Bellman-Ford 会在 O(|V||E|) 时间内为您提供所需的东西。即使您的图包含负加权边,这也有效,并且 Bellman-Ford 使用动态规划作为其核心。
但是,我必须补充一点,如果你的权重是非负的,你可以在 O(|E| log |E|) 的时间内从你的顶点 s 做 Dijkstra。
【讨论】:
初始化d[s] = 0。
对于每个顶点,计算:
d[v] = min {d[u] + w(u,v) | (u,v) is an edge}
d[v] = ∞ 如果v 没有传入边。
(算法总是停止,因为图是非循环的。)
【讨论】: