加权图中最短路径的数量

时间:2015-05-24 13:02:06

标签: algorithm graph

这是一个问题:    给定有向图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)

*似乎算法可能陷入无限循环,也许我可以忽略后沿? (因为最短路径总是很简单)

*这不是重复的 How to find the number of different shortest paths between two vertices, in directed graph and with linear-time?

在那个问题中,图表在这里是未加权的,它是加权的(边缘) 你认为这是对的吗? 感谢

2 个答案:

答案 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