【问题标题】:How to find all the shortest paths between two given vertices in an undirected graph?如何在无向图中找到两个给定顶点之间的所有最短路径?
【发布时间】:2014-12-21 15:39:49
【问题描述】:

图 G 是一个无向图,它的所有边的权重都相同。 u,v 是 2 个给定的顶点,如何在 O(|V|) 中求图 G 中 u 和 v 之间的最短路径数?

|V|代表G中的顶点数。

【问题讨论】:

  • 我觉得做不到。 O(|V|) 太严格了。 BFS(我认为这是答案的基础)采用O(|E|+|V|),您甚至需要 O(|E| + |V|) 才能正确读取图表。
  • @AerofoilKite 链接的问题要求找到所有最短路径。这个只要求计数它们。这是更容易的任务。
  • @amit,想法是一样的。除了存储访问过的节点,你必须做同样的工作
  • @AerofoilKite 不,不是——计算路径比生成路径容易得多。计算它们可能需要多项式时间,而生成它们 - 不能。我同意你可以通过生成所有路径并计算它们来解决这个问题——但这有点过头了。

标签: algorithm graph


【解决方案1】:

您可以使用 BFS 的计数变化。

这个想法是保存一个映射dict:(v,depth)->#paths 的字典(条目是顶点和当前深度,值是从源到具有所需深度的该顶点的路径数)。

在 BFS 的每次迭代中,您都会跟踪路径的当前深度,并将找到的路径数添加到下一个级别。

如果您有 3 条通往 x 的路径和 4 条通往 y 的路径,都在深度 3 上,并且都有边缘 (x,u),(y,u) - 那么有 7 条通往 u 的路径 - 的想法3 通向x+(x,u),4 通向y+(y,u)。

应该是这样的:

findNumPaths(s,t):
   dict = {} //empty dictionary
   dict[(s,0)] = 1 //empty path
   queue <- new Queue()
   queue.add((s,0))
   lastDepth = -1
   while (!queue.isEmpty())
       (v,depth) = queue.pop()
       if depth > lastDepth && (t,lastDepth) is in dict: //found all shortest paths
            break
       for each edge (v,u):
           if (u,depth+1) is not entry in dict:
               dict[(u,depth+1)] = 0
               queue.push((u,depth+1)) //add u with depth+1 only once, no need for more!
           dict[(u,depth+1)] = dict[(u,depth+1)] + dict[v,depth]

       lastDepth = depth
   return dic[t]

如果使用哈希表作为字典,运行时间是 O(V+E)。


另一种解决方案(更容易编程但效率较低)是:

 1. Build the adjacency  matrix of the graph, let it be `A`. 
 2. Set `Curr = I` (identity matrix)
 3. while Curr[s][t] != 0:
    3.1. Calculate Curr = Curr * A //matrix multiplication
 4. Return Curr[s][t]

它起作用的原因是(A^n)[x][y] 是图中A 中大小为n 的路径数表示从xy。我们找到第一个大于零的数字,并返回路径数。

【讨论】:

  • 第二种方案很聪明,但运行时间不能是O(V+E)。
  • @Gary33 不,第二个解决方案效率较低 - 但它优雅、漂亮且非常容易在 Matlab 中编程,因此我决定也添加它。第一个应该满足您的复杂性要求,但编程有点困难。
  • 感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 2021-05-25
  • 2023-04-11
  • 1970-01-01
  • 2012-12-18
  • 2015-02-19
  • 1970-01-01
相关资源
最近更新 更多