这是一个问题: 给定有向图G =(V,E),源顶点s $ epsilon V,我们知道G中的所有周期都是正权重(> 0)。在Bellman-Ford运行之后我们也得到了图表,这意味着对于V中的每个v,我们都知道d [v](从s到v的最短路径)和pi [v](v' s的前身)
描述一种算法,用于查找V中所有v的从s到v的最短路径数。算法必须在O(V + E)中运行
*我们无法在算法上编辑Bellman-Ford运行
这就是我的想法: 我们运行一个修改过的DFS,
算法(G,S):
1.DFS-Visit(G,s)
2. return count[v] foreach v in V
DFS-访问(G,U):
1.foreach v in Adj[u]
2.if d[v] == d[u] + w(u,v) && (u,v) is not a backedge
3.count[v] = count[v] + 1
4.DFS-visit(G,v)
*似乎算法可能陷入无限循环,也许我可以忽略后沿? (因为最短路径总是很简单)
在那个问题中,图表在这里是未加权的,它是加权的(边缘) 你认为这是对的吗? 感谢
答案 0 :(得分:1)
if d[v] == d[u] + w(u,v) && (u,v) is not a backedge
条件d[v]==d[u]+w(u,v)
在这里是最重要的。如果保证这永远不是一个备份,而且它保证你永远不会返回到你曾经去过的顶点。
的确,假设你回到了原来的顶点。那你有
d[v1]==d[v0]+w(v0,v1)
d[v2]==d[v1]+w(v1,v2)
...
d[v0]==d[vn]+w(vn,v0)
总结一切,我们发现
w(v0,v1)+w(v1,v2)+...+w(vn,v0)==0
这是一个零权重循环,但我们被告知没有这样的循环。
所以这个算法永远不会陷入无限循环;此外,如果您只留下满足d[v]==d[u]+w(u,v)
的边(即使图中没有图表也是如此),结果图将是非循环的。
因此,您可以运行在非循环图中查找多种方法的标准算法。事实上这就是你已经写过的(你的DFS
),请注意
count[v] = count[v] + 1
应该是
count[v] = count[v] + count[u]
答案 1 :(得分:0)
以问题中描述的方式修改的 DFS(根据接受的答案进行更正)允许多次访问一个节点,并可以导致指数时间算法(请参见下面的反例,了解发生这种情况的图的一般结构).
如果我们像在经典 DFS 中一样访问每个节点一次,该算法并不总是正确计算最短路径的数量。
反例
7个节点,8条边,权重均为1
1 -> 2
1 -> 5
2 -> 3
5 -> 3
3 -> 4
3 -> 6
4 -> 7
6 -> 7
一般结构看起来像这样
2 4
/ \ / \
1 3 7
\ / \ /
5 6
从节点 1 开始运行 Bellman-Ford 后:
d[1] = 0
d[2] = d[5] = 1
d[3] = 2
d[4] = d[6] = 3
d[7] = 4
从节点 1 到节点 7 有 4 条不同的最短路径:
1 2 3 4 7
1 2 3 6 7
1 5 3 4 7
1 5 3 6 7
但是应用 DFS 我们得到:
count[1] = 1
Visiting node 1: count[2] = 1
Visiting node 2: count[3] = 1
Visiting node 3: count[4] = 1
Visiting node 4: count[7] = 1
Visiting node 7: no outgoing arcs
Returning to node 4: no more neighbors
Returning to node 3: count[6] = 1
Visiting node 6: count[7] = 2
Node 7 already visited, so we skip it
Returning to node 6: no more neighbors
Returning to node 3: no more neighbors
Returning to node 2: no more neighbors
Returning to node 1: count[5] = 1
Visiting node 5: count[3] = 2
如果不允许多次访问节点,这就是算法结束的地方,因此计数 [7] 将保持为 2,这是不正确的(正确的应该是 4)。如果我们允许多次访问一个节点,运行时间将是 2^n 的量级。
正确的算法
如 Petr 的回答所示,最短路径上的边形成有向无环图 (DAG)。我们需要对这个 DAG 的节点进行拓扑排序,并按照拓扑顺序对节点应用计数算法。运行时间为 O(n + m):拓扑排序需要遍历一次图,计数算法需要遍历一次图。
在反例中展示了正确的算法
One possible topological order: 1 2 5 3 4 6 7
Visiting nodes in this order:
count[1] = 1
Visiting 1: count[2] = 1, count[5] = 1
Visiting 2: count[3] = 1
Visiting 5: count[3] = 2
Visiting 3: count[4] = 2, count[6] = 2
Visiting 4: count[7] = 2
Visiting 6: count[7] = 4