Algorithm 枚举所有可能路径的算法
考虑下图: 我试图找到一种方法来枚举从源节点到目标节点的所有可能路径。例如,从A到E,我们有以下可能的路径:Algorithm 枚举所有可能路径的算法,algorithm,graph-theory,graph-algorithm,depth-first-search,breadth-first-search,Algorithm,Graph Theory,Graph Algorithm,Depth First Search,Breadth First Search,考虑下图: 我试图找到一种方法来枚举从源节点到目标节点的所有可能路径。例如,从A到E,我们有以下可能的路径: A B C D E A B C E A C D E A C E 请注意,对于CDE,实际上有两条路径,因为其中一条路径使用边F3,另一条使用边F5。另外,由于a和C之间有一个循环,最终可能会有无限多条路径,但出于这个目的,我只对从源到目标的路径上没有重复节点的路径感兴趣 我编写了一个深度优先搜索(DFS)算法,但问题是当两个节点之间有多条边(如上面的边F3和F5)时,我不确定如何处理
A B C D E
A B C E
A C D E
A C E
请注意,对于CDE,实际上有两条路径,因为其中一条路径使用边F3,另一条使用边F5。另外,由于a和C之间有一个循环,最终可能会有无限多条路径,但出于这个目的,我只对从源到目标的路径上没有重复节点的路径感兴趣
我编写了一个深度优先搜索(DFS)算法,但问题是当两个节点之间有多条边(如上面的边F3和F5)时,我不确定如何处理它。我的算法只返回路径acde
和ace
,而不是其他路径。在A B C E
的情况下,我理解其原因,因为它从A开始,然后转到C并构建这些路径,但当DFS返回到节点B时,它会尝试转到C,但C已经被访问,因此它会停止
不管怎样,我只是想知道是否有办法做到这一点,或者这可能是NP完全的
如果您想查看我的DFS,代码如下(很抱歉宏滥用,我在竞赛编程中使用这些,所以这有点习惯)
无论如何,我只是想知道是否有办法做到这一点,或者这可能是NP完全的。我不相信你能输出
n代码>多项式时间内的可能路径。如果每个节点都连接到另一个节点,那么这就是如何得到的
但问题是,如果两个节点之间有多条边(如上面的边F3和F5)
所以,你要考虑边<代码> f3< /代码>和<代码> f5<代码>,对吗?在调用dfs
之前删除重复边可能是最简单的选择
因为它从A开始,然后转到C并构建这些路径,但当DFS返回到节点B时,它会尝试转到C,但C已被访问,因此它会停止。
那么,让我们把C
标记为不再访问
void dfs(char at) {
vis[at] = true;
// do stuff with 'at'
vis[at] = false;
}
我的猜测是,如果你说
J->K->L->O->T
J->M->N->O->T
我认为你的“我们以前到过这里吗”测试不应该只看当前节点,而是看你到达那里的路径。因此,不要检查“O”,检查“JMNO”和“JKLO”。以下是使用BFS的方法:可以使用以下(python
)函数(使用两个节点之间的递归路径查找函数修改BFS)查找非循环图中两个节点之间的所有可能路径:
例如,对于以下图(DAG)G(通过从给定图中移除有向圈和多条边),由
G = {'A':['B','C'], 'B':['C'], 'C':['D', 'E', 'F'], 'D':['E'], 'E':['I'], 'F':['G', 'H']}
如果我们想查找节点'A'
和'E'
之间的所有路径(使用上述定义的函数查找所有路径(查找所有父节点(G,'A'),'A','E'))
,它将根据需要返回以下路径:
# ACDE
# ABCDE
# ACE
# ABCE
我怀疑这是topcoder的问题。在这种情况下,输入大小的限制是什么?嗨,Kit,很高兴在这里遇到你!这不是来自algo竞赛的TC问题,该搜索将在DB中完成。因此,大小几乎可以是无限的。我在想也许没有真正的解决办法,你觉得呢?很高兴见到你:)如果输入没有限制,那么你将很难输出所有的n!解决。但是如果结果的大小是有限的或者它是某种非常稀疏的图,这可能会起作用。在应用程序中,您忘记了从节点B开始的边。这可以解释为什么它找不到路径A B C D E和A B C E。@Patrick-Yep,也注意到了,谢谢!谢谢,DFS和回溯按照您的建议进行了工作。这一点很好,但我相信Nikita建议的回溯方法可以解决这个问题。当它到达T时,它将一路“回溯”到J(将节点标记为沿途未访问),然后它将再次沿着路径递归以获得第二条路径。
from collections import defaultdict
# modified BFS
def find_all_parents(G, s):
Q = [s]
parents = defaultdict(set)
while len(Q) != 0:
v = Q[0]
Q.pop(0)
for w in G.get(v, []):
parents[w].add(v)
Q.append(w)
return parents
# recursive path-finding function (assumes that there exists a path in G from a to b)
def find_all_paths(parents, a, b):
return [a] if a == b else [y + b for x in list(parents[b]) for y in find_all_paths(parents, a, x)]
G = {'A':['B','C'], 'B':['C'], 'C':['D', 'E', 'F'], 'D':['E'], 'E':['I'], 'F':['G', 'H']}
# ACDE
# ABCDE
# ACE
# ABCE