查找未加权无向图中两个节点之间的所有最短路径

时间:2013-01-03 17:31:14

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

我需要帮助找到未加权无向图中两个节点之间的所有最短路径。

我能够找到使用BFS的最短路径之一,但到目前为止,我失去了如何找到并打印出所有这些路径。

我可以使用算法/伪代码的任何想法吗?

7 个答案:

答案 0 :(得分:29)

作为一个警告,请记住,图中两个节点之间可能存在指数级的最短路径。任何算法都可能需要指数时间。

也就是说,对BFS进行了相对简单的修改,您可以将其用作预处理步骤,以加快所有可能路径的生成。请记住,当BFS运行时,它会在“图层”中向外进行,获得距离0,距离1,距离2等所有节点的最短路径.BFS背后的激励理念是距离为k + 1的任何节点从起始节点起必须通过边缘连接到距起始节点距离k的某个节点。 BFS通过向距离为k的节点找到长度为k的路径,然后将其延伸一些边缘,在距离k + 1处发现该节点。

如果您的目标是找到所有最短路径,那么您可以通过将每条路径扩展到距离为k的所有节点的距离为k +的节点来修改BFS 1他们连接到而不是选择单个边缘。为此,请按以下方式修改BFS:无论何时通过在处理队列中添加其端点来处理边缘,都不要立即将该节点标记为已完成。相反,将该节点插入到注释的队列中,使用哪个边缘来获取它。如果有多个节点链接到队列,这可能会让您多次将同一节点插入队列。从队列中删除节点时,您将其标记为已完成,并且永远不会再将其插入队列。类似地,您将存储多个父指针,而不是存储单个父指针,每个指针用于链接到该节点的每个节点。

如果您执行此修改后的BFS,您将得到一个DAG,其中每个节点将是起始节点并且没有外出边缘,或者距离起始节点的距离为k + 1,并且将指向它所连接的距离k的每个节点。从那里,您可以通过列出从您选择的节点返回到DAG内的起始节点的所有可能路径,重建从某个节点到起始节点的所有最短路径。这可以递归地完成:

  • 从起始节点到自身只有一条路径,即空路径。
  • 对于任何其他节点,可以通过跟随每个传出边缘找到路径,然后递归地扩展这些路径以产生返回到起始节点的路径。

希望这有帮助!

答案 1 :(得分:5)

@templatetypedef是正确的,但他忘了提及在将任何父链接添加到节点之前必须完成的距离检查。这意味着se在每个节点中保持与源的距离,并为子节点增加1。我们必须跳过这个增量和父增加,以防孩子已经被访问并且距离较短。

public void addParent(Node n) {
    // forbidding the parent it its level is equal to ours
    if (n.level == level) {
        return;
    }
    parents.add(n);

    level = n.level + 1;
}

可以通过以下链接找到完整的Java实现。

http://ideone.com/UluCBb

答案 2 :(得分:2)

我在解决这个https://oj.leetcode.com/problems/word-ladder-ii/

时遇到了类似的问题

我试图处理的方法是首先使用BFS找到最短距离,假设最短距离为d。现在应用DFS并在DFS递归调用中不要超出递归级别d。

然而,这最终可能会探索@templatetypedef所提到的所有路径。

答案 3 :(得分:1)

首先,使用广度优先搜索找到所有节点的起始距离。

(如果有很多节点,您可以使用A *并在队列顶部有distance-to-start > distance-to-start(end-node)时停止。这将为您提供属于某个最短路径的所有节点)

然后从末端节点回溯。只要节点连接到两个(或更多)节点,启动距离较短,就可以分支到两个(或更多)路径。

答案 4 :(得分:0)

templatetypedef你的答案非常好,非常感谢你(!!),但它错过了一点:

如果您有这样的图表:

A-B-C-E-F
  |     |
  D------

现在让我们想象一下我想要这条道路:

A -> E.

它会像这样扩展:

 A-> B -> D-> C -> F -> E.

那里有问题, 你将F作为E的父级,但是

 A->B->D->F-E 

更长

 A->B->C->E.
您必须跟踪您非常乐意添加的父母的距离。

答案 5 :(得分:0)

步骤1:通过BFS从源遍历图形并为每个节点分配距离源最小的距离

步骤2:分配给目标节点的距离是最短的长度

步骤3:从源,沿着所有路径进行DFS搜索,其中最小距离逐个增加,直到达到目标节点或达到最短长度。每当到达目标节点时打印路径。

答案 6 :(得分:-1)

当你找到你想要的东西时,BFS会停止。

您必须修改算法,以便在找到第一个路径时继续执行。 (删除return语句并以某种方式保存路径。

在检查具有最短路径的结束节点的级别的最后一个节点之后,您可以结束执行。 (最短路径的所有结束节点都处于同一级别)


此外,已知的算法可以找到所有最短路径:

Floyd–Warshall algorithm(它有伪代码)

Johnson's algorithm