在非循环有向图中找到两个节点之间的所有路径的有效方法

时间:2015-06-04 14:31:57

标签: algorithm data-structures graph network-programming julia

我想在图中找到两个节点之间的所有路径。我写了一个递归函数,借助深度优先搜索算法找到所有路径。但对于较大的图形,效率非常低,因此我不能将它用于我的程序。

我正在考虑为我的问题实施迭代方法。这对我来说非常耗时。所以有人知道这是否有意义?

在这种情况下迭代方式是否更有效?或者是否可以优化我的递归方法?

我目前的职能:

function RecDFS(g::GenericGraph, visited)
    nodes = out_neighbors(visited[length(visited)], g) 

    for i in nodes
    if in(i,visited)
        continue
    end

    if i.label == "End"
        push!(visited,i)
        println(visited) # print every path from the first node in visited to the node with the label End
        pop!(visited)
        break
    end

    # continue recursive..
    for i in nodes
        if (in(i, visited) || i.label == "End")
            continue
        end
        push!(visited,i)
        depthFirstSearchAllI(g, visited)
        pop!(visited)
    end
end

4 个答案:

答案 0 :(得分:3)

你试图解决的问题实际上是NP难问题,这意味着它还没有多项式时间算法!

所以你可以为你的问题找到一些优化,但你不能让它运行得足够快!

与优化一样,您可以执行以下操作。首先,您在问题主题中提到您的输入是DAG图,而DAG根据定义具有以下属性:

DAG的两个不同连接部分中的两个节点之间没有路径。

所以,如果你有一个DAG连接部分中的节点列表(这在多项式时间内是可以实现的),你可以很容易地划掉很多无望的组合。

在使程序迭代时,您可以轻松地使用堆栈。只需用stack.push(节点)替换每个递归调用,并将代码的遍历部分放在一段时间内(堆栈不为空),然后逐个弹出节点,除非没有。应该这样做。

答案 1 :(得分:2)

经过一些想法,我找到了解决问题的好方法。看看这个示例代码:

function RecDFS(g::GenericGraph, visited)
   nodes = out_neighbors(visited[length(visited)], g) 
   if(checkPath(visited))
       for i in nodes
           if in(i,visited)
              continue
           end

           if i.label == "End"
               push!(visited,i)
               println(visited) # print every path from the first node in visited to the node with the label End
               pop!(visited)
               break
           end
        end

   # continue recursive..
       for i in nodes
           if (in(i, visited) || i.label == "End")
               continue
           end
           push!(visited,i)
           depthFirstSearchAllI(g, visited)
           pop!(visited)
       end
   end
end

总而言之,我刚刚添加了一个if语句。如果路径到目前为止有效,则函数checkPath(visited)返回true。如果路径(或路径段)无效,则函数结束。

对于我的具体问题,这是一个非常好的解决方案。它在我的测试运行中快了100倍,对于我的500个节点和16000个边缘的最大问题实例只需要15秒。

非常感谢Ashkan Kzme和Rob的帮助。

答案 2 :(得分:1)

在DAG中执行topological sort个顶点,以获得<Connector port="listeningport" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" /> 。假设您的起始节点为[v0, v1, ... , vn],即您的目的地vs。 (如果vt则没有路径)

然后,对于s > t中的每个i,计算从s+1 .. tP(i)的路径vs,如下所示:

  • 如果有一条边vi,那就是一条路径(长度为1)
  • 查找所有vs -> vij并且边缘为s < j < i。添加从vj -> vi获取路径并附加边P(j)
  • 获取的所有路径
  • 注意。对于给定的vj -> vi,无法保证从ivs
  • 根本没有任何路径

正如已经评论过的那样,可能存在指数级的路径,因此输出所有路径通常不能在低于指数的时间内完成。但是,您可以使用此方法计算线性时间内的路径数。

答案 3 :(得分:0)

您可以使用队列进行深度优先搜索,从而保存您刚刚经过的节点。