关于算法:查找DAG上两个节点之间的所有路径

Finding all paths between two nodes on a DAG

我有一个具有以下邻接表的DAG

1
2
3
4
5
6
L | G, B, P
G | P, I
B | I
P | I
I | R
R | \\

我想找到从LR的所有路径。我知道我必须做某种DFS,这就是我到目前为止所要做的。 (请原谅)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function dfs(G, start_vertex) {

    const fringe = []
    const visited = new Set()
    const output = []
    fringe.push(start_vertex)

    while (fringe.length != 0) {
        const vertex = fringe.pop()
        if (!visited.has(vertex)) {
            output.push(vertex)
            for (neighbor in G[vertex].neighbors) {
                fringe.push(neighbor)
            }
            visited.add(vertex)
        }
    }

    return output
}

dfs(G,"L")的输出是[ 'L', 'P', 'I', 'R', 'B', 'G' ],这确实是该图的深度优先遍历,但不是我要寻找的结果。经过一番搜索之后,我意识到可能有一个递归的解决方案,但是有人对此问题发表了评论,称其为" NP难",还有一些我不理解的关于"指数路径"的问题。


这个问题确实很棘手,因为两个节点之间的可能路径数与节点数成指数关系。因此无法避免出现最坏情况的指数运行时。


所有从head到顶点vertex的路径都可以拆分为头部为head||v的路径,其中vhead的最终顶点相邻,除非head的最终顶点已经为 :(伪javascript,可能有语法问题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function print_all_rec(G, head, vertex){
  if(head[head.length-1] == vertex){
    print(head); //we're here
    return;
  }
  for(v in head[head.length-1].neighbors){
    var newHead = head; newHead.append(v);
    print_all_rec(G, newHead, vertex);
  }
}

function print_all_routes(G, from, to){
  var start = [];
  start.append(from);
  print_all_rec(G, start, to);
}