简体   繁体   English

使用递归回溯查找有向图中的所有循环

[英]Finding all cycles in a directed graph using recursive backtracking

I am working on finding cycles in directed graph using recursive backtracking.我正在使用递归回溯在有向图中寻找循环。 There is a suggested pseudocode for this here , which is here:有此建议的伪代码在这里,这是在这里:

dfs(adj,node,visited):  
  if (visited[node]):  
    if (node == start):  
      "found a path"  
    return;  
  visited[node]=YES;  
  for child in adj[node]:  
    dfs(adj,child,visited)
  visited[node]=NO;

Call the above function with the start node:使用起始节点调用上述函数:

visited = {}
dfs(adj,start,visited)

While this is not the most efficient algorithm when compared to Tarjans algorithm , this is simple enough me for me to understand.虽然与Tarjans algorithm相比,这不是最有效的算法,但这对我来说已经足够简单了。 Currently, this code does not have a count of number cycles detected.目前,此代码没有检测到循环次数。

I implemented this in Java:我在 Java 中实现了这个:

//this is the main method that calls the helper DFS which runs on each node
public int allCyclesDirectedmain(){
    //this initializes all vertices
    clearAll();
    int[] count = new int[1];
    for (Vertex v: vertexMap.values()){
        //System.out.println(v.name);
        //clearAll();
        dfs(v,v,count);
    }
    return count[0];
}

//start and v are same when the method first fires.
public void dfs(Vertex start, Vertex v,int[] count){
   if (v.isVisited){
       if (start==v){
           //found a path
           count[0]++;
       }
       return ;
   }
   v.setVisited(true);
   for (Edge e : v.adj){
       Vertex next = e.target;
       dfs(start,next,count);
   }
   v.setVisited(false);
}

For the graph with following edges:对于具有以下边的图:
(1 2),(2 3),(3 1),(2 5),(5 6),(6 2) -- I get 6 cycles as output. (1 2),(2 3),(3 1),(2 5),(5 6),(6 2) - 我得到 6 个周期作为输出。

(1 2),(2 3),(3 4),(4,1),(2 5),(5 6),(6 2) -- I get 7 cycles as output. (1 2),(2 3),(3 4),(4,1),(2 5),(5 6),(6 2) - 我得到 7 个周期作为输出。

I can see that my current code does cycle detection for each vertex that are already part of a previously detected cycle (eg: a cycle with three nodes gives me three cycles for each individual nodes while this must be one).我可以看到我当前的代码对每个顶点进行了循环检测,这些顶点已经是先前检测到的循环的一部分(例如:具有三个节点的循环为每个单独的节点提供了三个循环,而这必须是一个)。 I need some tips here as to what is going wrong and some fix.我需要一些关于出现问题和修复的提示。

For (1 2),(2 3),(3 1) , you're calling:对于(1 2),(2 3),(3 1) ,您正在调用:

  • dfs(vertex1, vertex1, count) , which gives you the cycle 1 -> 2 -> 3 -> 1 . dfs(vertex1, vertex1, count) ,它为您提供循环1 -> 2 -> 3 -> 1
  • dfs(vertex2, vertex2, count) , which gives you the cycle 2 -> 3 -> 1 -> 2 . dfs(vertex2, vertex2, count) ,它为您提供循环2 -> 3 -> 1 -> 2
  • dfs(vertex3, vertex3, count) , which gives you the cycle 3 -> 1 -> 2 -> 3 . dfs(vertex3, vertex3, count) ,它为您提供循环3 -> 1 -> 2 -> 3

So you're counting the same cycle multiple times.所以你多次计算同一个周期。

The simplest fix I can think of is simply setting the visited flag after the dfs call.我能想到的最简单的解决方法是在dfs调用后简单地设置访问标志。

public int allCyclesDirectedmain(){
    clearAll();
    int[] count = new int[1];
    for (Vertex v: vertexMap.values()){
        dfs(v,v,count);
        v.setVisited(true); // <---
    }
    return count[0];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM