循环无向图中的所有可能路径

时间:2010-06-17 05:02:33

标签: java c++ algorithm

我正在尝试开发一种算法,用于识别图形中两个节点之间的所有可能路径,如下例所示:

image

事实上,我只需知道哪些节点出现在所有现有路径中。

网上的

只有关于DFS,A *或dijkstra的引用,但我认为它们在这种情况下不起作用。

有谁知道如何解决它?

5 个答案:

答案 0 :(得分:4)

您可以使用DFS找到所有路径,例如| Vlad描述。要找到每个路径中出现的节点,您可以只维护一个布尔数组,说明到目前为止每个节点是否都出现在每个路径中。当DFS找到路径时,请遍历路径中的每个顶点而不是,并将相应的数组值设置为false。完成后,只有值为true的顶点才会出现在每个路径中。

伪代码:

int source;
int sink;
int nVerts;
bool inAllPaths[nVerts]; // init to all true
bool visited[nVerts]; // init to all false
stack<int> path; // init empty

bool dfs(int u)
  if (visited[u])
    return;
  if (u == sink)
    for i = 0 to nVerts-1
      if !stack.contains(i)
        inAllPaths[i] = false;
    return true;
  else
    visited[u] = true;
    stack.push(u);
    foreach edge (u, v)
      dfs(v);
    stack.pop();
    visited[u] = false;
    return false;


main()
  dfs(source);
  // inAllPaths contains true at vertices that exist in all paths
  // from source to sink.

但是,这种算法效率不高。例如,在n个顶点的完整图形中(所有顶点都与所有其他顶点具有边缘),路径的数量将为n! (n阶乘)。

更好的算法是分别检查每个顶点的每个路径中是否存在。对于每个顶点,尝试找到从源到接收器的路径,而不必去往该顶点。如果找不到,那是因为顶点出现在每个路径中。

伪代码:

// Using the same initialisation as above, but with a slight modification
// to dfs: change the foreach loop to
foreach edge (u, v)
  if (dfs(v))
    return true; // exit as soon as we find a path

main()
  for i = 0 to nVerts-1
    set all visited to false;
    if (inAllPaths[i])
      visited[i] = true;
      if (dfs(source))
        inAllPaths[i] = false;
      visited[i] = false;

不幸的是,在搜索路径时,这仍然是指数最坏的情况。您可以通过将搜索更改为广度优先搜索来解决此问题。如果我没弄错的话,这应该会给你O(VE)表现。

答案 1 :(得分:1)

从起始节点运行DFS,并保留自己的堆栈,告诉您在任何给定时间看到的节点。注意循环:当你看到一个节点两次时,你有一个循环,你必须中止你当前的路径。注意不要访问节点的父节点,以避免长度为1的循环(向DFS函数添加parent参数,这将有所帮助)。

然后,当您到达目标节点时,输出堆栈的内容。

DFS完成后,您将拥有所有路径。

答案 2 :(得分:1)

对于这个问题,我首先会在你的一个目标节点u上得到一个由DFS组成的树。然后,为根据第二个目标节点v的子树中的所有节点着色,比如蓝色。

For each node k in subtree s, 
    if k has an edge to a non-blue node x 
    then k is true and x is true.

另外,将v标记为true。最后,我会使用递归函数到叶子。像

这样的东西
function(node n){
    if(n = null)
        return false
    if(function(n.left) or function(n.right) or n.val){
        n.val = true
        return true
    }
    else
        return false
}

标记为true的所有节点都是从u到v的路径中的节点。运行时最多(Vertices + Edges),因为DFS =(V + E)for循环最多(V)最多递归(V)

答案 3 :(得分:1)

我知道已经有一段时间了,但我来到这里寻找一些算法来查找SQL或Java中的所有路径(不仅是最短路径)而且我发现了这三个(我只是发布它们以保持概念组织):< / p>

如果您在评论中添加start with n1...行和where n2...行,则查询将返回所有图表中的所有路径。

答案 4 :(得分:0)

一个顶点位于从A到B的路径上,如果它可以从A到达,并且B可以从它到达。

所以:从A开始进行洪水填充。标记所有这些顶点。 从B开始进行洪水填充,然后反向跟随边缘。您遇到的所有标记顶点都是解决方案的一部分。