我需要帮助找到未加权无向图中两个节点之间的所有最短路径。
我能够找到使用BFS的最短路径之一,但到目前为止,我失去了如何找到并打印出所有这些路径。
我可以使用算法/伪代码的任何想法吗?
答案 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实现。
答案 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(它有伪代码)