【问题标题】:How to find all shortest paths如何找到所有最短路径
【发布时间】:2013-11-28 03:31:59
【问题描述】:

我有一个图表,我想找到两个节点之间的所有最短路径。我通过 BFS 找到了两个节点之间的最短路径。但是,如果存在多条路径,它只会给我一条最短路径。

我怎样才能使用 BFS 获得所有这些?

我已经使用著名的 BFS 伪代码实现了我的代码。
另外,我有一个邻接列表向量,其中包含所有节点的邻接顶点。

【问题讨论】:

  • 如果您可以提供代码,我们可以轻松地帮助您。我相信这只是一个简单的修改。 =)
  • @justhalf 我已经编辑了我的代码。感谢回复
  • @Dukeling 感谢您的回复。我不想找到所有顶点之间的所有路径。我想找到的是 2 个特定节点之间的所有最短路径。
  • 你应该发布你的实际代码,而不是伪代码。
  • 您可以使用dfs查找从A到B的所有路径。根据长度对路径进行排序,然后您可以找到所有最短路径。

标签: algorithm graph-theory breadth-first-search shortest-path


【解决方案1】:

您可以通过为每个节点维护一个父节点列表或向量来轻松做到这一点。 如果距离起始节点相同距离的两个或多个节点(例如 X、Y、Z)通向另一个节点 M,则将所有 X、Y 和 Z 作为 M 的父节点。

在向节点添加父节点时,您只需添加一个检查以查看该父节点是否与之前的父节点处于同一级别。

level 是指到起点的距离。

通过这种方式,您可以通过追溯父向量来获得所有最短路径。 下面是我的 C++ 实现。

我希望你知道如何从目的地开始打印路径,追踪父母并到达起点。

编辑:伪代码

bfs (start , end)

    enqueue(start)
    visited[start] = 1

    while queue is NOT empty

        currentNode = queue.front()
        dequeue()

        if(currentNode == end)
            break

        for each node adjacent to currentNode

            if node is unvisited
                visited[node] = visited[curr] + 1
                enqueue(node)
                parent[node].add(currentNode)

            else if(currentNode is in same level as node's parents)
                parent[node].add(currentNode)

return 

【讨论】:

  • 感谢您,我正确获取了父母信息,但是,我不知道如何通过不递归的回溯打印路径,您有什么提示吗?
  • 是的,您可以使用堆栈并迭代地执行此操作。我会尽快发布伪代码。
  • banarun 发布的答案将适用于打印所有路径。使用父向量而不是邻接列表。从目的地开始,追踪到起始节点的所有路径。
【解决方案2】:

如果图表很大,找到从头到尾的所有路径然后选择最短的路径可能会非常低效。这是一个更好的算法:

  1. 使用 BFS,标记每个节点到起始节点的距离。到达结束节点时停止。

    def bfs_label(start, end):
        depth = {start: 0}
        nodes = [start]
        while nodes:
            next_nodes = []
            for node in nodes:
                if node == end:
                    return depth
    
            for neighbor in neighbors(node):
                if neighbor not in depth:
                    depth[neighbor] = depth[node] + 1
                    fringe.append(neighbor)
    
  2. 使用 DFS,找到从开始节点到结束节点的所有路径,使得路径的每一步深度严格增加。

    def shortest_paths(node, end, depth, path=None):
        if path is None:
            path = []
    
        path.append(node)
    
        if node == end:
            yield tuple(path)
        else:
            for neighbor in neighbors(node):
                if neighbor in depth and depth[neighbor] == depth[node]+1:
                    for sp in shortest_paths(neighbor, end, depth, path):
                        yield sp
    
        path.pop()
    

【讨论】:

    【解决方案3】:

    更简单的方法是使用 dfs 查找从源到目标的所有路径。现在找到这些路径中最短的路径。这是一个 sudo 代码:

    dfs(p,len)
          if(visited[p])
             return
    
          if(p== destination)
              paths.append(len)
    
              return
          visited[p]=1
          for each w adjacent to p
               dfs(w,len+1)
          visited[p]=0
    

    您可以通过维护路径数组来找到路径。我会把它留给你作为任务

    【讨论】:

    • 抱歉,这是错误的,您不能使用 dfs 查找从源到目标的所有路径。例如,您将错过以下两种情况之一:1->2->3->4 和 1->3->4。如果要查找“全部”路径,则需要递归,而不是 dfs。
    • 对了,这个问题是重复的stackoverflow.com/questions/14144071/…
    • 请注意,这是一种非常低效的做事方式。考虑一个具有十亿个节点的图,两个目标节点之间的最短路径长度为 5。您将探索所有节点,而不仅仅是与源节点的距离为 5。 Modified BFS 好多了。
    • @PhamTrung DFS 是递归的。对于1节点,它会先到2,找到1->2->3->4,然后回溯到1,再到3,找到1->3->4。你重复的评论可能更适合作为对 question 的评论或重复的标志(我只是标记它)。
    • @Dukeling,我的意思是通过递归进行完整搜索:) 抱歉,这段代码不是 dfs,我误解了它:D 并且将路径存储在数组中并不是一个好主意,因为路径已经可以包含当前节点,需要进一步检查
    【解决方案4】:

    我们可以使用简单的 BFS 算法来查找所有最短路径。我们可以将路径与当前节点一起维护。我在下面提供了指向 python 代码的链接。 https://gist.github.com/mridul111998/c24fbdb46492b57f7f17decd8802eac2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多