这不适用于家庭作业。我正在通过练习测试(未评分)为几周的决赛做准备。我不知道该去哪儿。
令G =(V; E)为n个顶点和m个边的DAG(有向无环图)。
E的每个边(u; v)具有权重w(u; v),其是任意值(正,零或负)。
设k为输入正整数。
如果路径不超过k个边,则G中的路径称为k-link路径。设s和t为G的两个顶点。从s到t的k-link最短路径被定义为从s到t的k-link路径,其具有所有可能的k-link s-to中的边缘权重的最小总和。 G.中的-t路径。
设计一个 O(k(m + n))时间算法来计算从s到t的k-link最短路径。
对此算法的任何帮助将不胜感激。
答案 0 :(得分:2)
让dp[amount][currentVertex]
给出G中最短路径的长度,该路径从s开始,在currentVertex
结束,由amount
边组成。
make all values of dp unset
dp[0][s] = 0
for pathLength in (0, 1, .. k-1) // (1)
for vertex in V
if dp[pathLength][vertex] is set
for each u where (vertex, u) is in E // (2), other vertex of the edge
if dp[pathLength+1][u] is unset or greater than dp[pathLength][vertex] + cost(vertex, u)
set dp[pathLength+1][u] = dp[pathLength][vertex] + cost(vertex, u)
best = dp[k][t]
for pathLength in (0, 1, .. k)
if dp[pathLength][t] < best
best = dp[pathLength][t]
上面的算法将给出从G到s的k-link最短路径的长度。它的时间复杂度由循环的复杂性决定(1)。单独的循环(1)具有强制性O(k),而其内部 - (2)简单地遍历图形。如果使用邻接表,则(2)可以在O(n + m)中实现。因此总体复杂度为O(k *(n + m))。
但是,这只会给出路径的长度,而不是路径本身。您可以通过为dp[][]
的每个值存储上一个顶点来修改此算法。因此,每当您为某些变量dp[pathLength+1][u]
,dp[pathLength][vertex] + cost(vertex, u)
,vertex
设置u
的值为pathLength
时,您就会知道之前使用过的顶点是vertex
。因此,您可以将其存储为prev[pathLength+1][u] = vertex
。
之后,您可以获得您想要的路径。我们的想法是使用您在prev
中创建的链接:
pLen = pathLength such that dp[pathLength][t] is minimal
curVertex = t
path = [] // empty array
while pLen >= 0
insert curVertex in the beginning of path
curVertex = prev[pLen][curVertex]
pLen = pLen - 1
path
存储了G中从s到t的k-link最短路径。