我有一个带加权边的连接DAG。权重可以是正数或负数。我有一个名为root的起始节点和一个名为goal的目标节点。我需要找到一条从根到目标的路径,以便在O(V + E)时间内净重尽可能小(如果净重是-ve甚至更好)。
我提出了以下伪代码,它几乎与Dijkstra相同,只是它只进入目标节点而不是所有节点。
Q = PriorityQueue()
Q.insert(root, 0)
while (Q is not empty) {
node = Q.extractMin()
if (node == goal) {
return path from node to goal
}
else {
for (x in adjacent[node]) {
Q.insert(x, weight[x])
}
}
此算法有效吗?另外,我不太确定这是否必然是O(V + E)。
P.S。:当我遍历图表时,当前节点的权重应始终为&lt; = k?如何找到最短路径,使得整个路径中该路径的权重总是在O(V + E)时间内<= k,只要它存在于图中?
答案 0 :(得分:1)
有一个非常简单的算法来解决David回答中描述的重现:我们可以使用深度优先搜索和memoization来确保每次我们需要解决结果的所有子问题当前节点已经知道。这隐含地导致我们需要的拓扑顺序:
for all nodes x:
dis[x] = UNKNOWN
def dfs(x):
if x == goal: return 0
if dis[x] != UNKNOWN: return x
dis[x] = infinity
for all edges (x,y) with weight w:
dis[x] = min(dis[x], w + dfs(y))
return dis[x]
结果只是dfs(root)
对于想要找到没有前缀超过权重 k 的最短路径的情况,您可以使用目标中的反向DFS:
for all nodes x:
dis[x] = UNKNOWN
def rdfs(x):
if x == root: return 0
if dis[x] != UNKNOWN: return x
dis[x] = infinity
for all edges (y,x) with weight w:
dis[x] = min(dis[x], w + rdfs(y))
if dis[x] > k:
dis[x] = infinity
return dis[x]
解决方案是rdfs(goal)
。
答案 1 :(得分:0)
这里的关键是非循环有向图。如果你放松(即设置d(w)= min(d(w),d(v)+ length(v-> w)))topological order中的弧,那么每个弧,一旦放松,保持放松。通过贝尔曼 - 福特的正确性证明,这意味着距离标签d是正确的。