为了在DAG(有向无环图)中找到最长路径,我知道两种算法:算法1:对排序结果使用动态规划 + 进行拓扑排序。或者算法2:使用深度优先搜索枚举DAG中的所有路径,并记录最长路径。似乎使用DFS枚举所有路径的复杂度比算法1要好,这是真的吗?
A->B->C
;你从B开始DFS,到达C并停止;然后从A重新开始,到达B并再次停止,因为你已经访问了C。DFS找到的两条路径,B-C
和A-B
,长度都为1;最长的路径A-B-C
长度为2。 - Sergey KalinichenkoA->B,C ; B->D ; C->D ; D->E,F ; E->G ; F->G
。 A
是源,因此您从它开始探索。 您走过 A-B-D-E,G
,回到 D
,尝试 A-B-D-F-G
,回到 A
,尝试 A-C-D
,并停止,因为现在已经完全探索了 D
。 如果按权重计算的最长路径是 A-C-D-E-G
,则深度优先搜索无法找到它。 - Sergey Kalinichenko使用“深度优先搜索”列举有向无环图(DAG)中的所有路径:
import numpy as np
def enumerate_dag(g):
def enumerate_r(n, paths, visited, a_path = []):
a_path += [n]
visited[n] = 1
if not g[n]:
paths += [list(a_path)]
else:
for nn in g[n]:
enumerate_r(nn, paths, visited, list(a_path))
paths, N = [], len(g)
visited = np.zeros((N), dtype='int32')
for root in range(N):
if visited[root]: continue
enumerate_r(root, paths, visited, [])
return paths
visited
的使用:你设置了它,但没有用它来决定是否应该继续遍历。这不是所谓的深度优先搜索,因为DFS不会访问已经完全探索过的节点。DFS和你的代码之间最大的区别在于,你的代码效率极低。尝试重复相同的钻石图案五十次,你就会知道我的意思:你的程序将探索所有 2^50
条路径,这是非常多的路径需要探索。 - Sergey Kalinichenkofor each node with no predecessor :
for each of his leaving arcs, E=1.
for each node whose predecessors have all been visited :
for each of his leaving arcs, E=max(E(entering arcs))+1.
当所有节点被处理完成时,max_path是边缘中最高的E。