首页 文章

使用递归回溯在有向图中查找所有周期

提问于
浏览
3

我正在使用递归回溯来查找有向图中的循环 . 这个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;

使用start节点调用上面的函数:

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

虽然与 Tarjans algorithm 相比,这不是最有效的算法,但这对我来说很容易理解 . 目前,此代码没有检测到的数字周期数 .

我用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);
}

对于具有以下边缘的图形:
(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) - 输出为7个周期 .

我可以看到我的当前代码对已经是先前检测到的周期的一部分的每个顶点进行循环检测(例如:具有三个节点的循环为每个单独的节点提供三个循环,而这必须是一个) . 我需要一些关于出了什么问题和一些修复的提示 .

1 回答

  • 3

    对于 (1 2),(2 3),(3 1) ,您正在致电:

    • dfs(vertex1, vertex1, count) ,它给你循环 1 -> 2 -> 3 -> 1 .

    • dfs(vertex2, vertex2, count) ,它给你循环 2 -> 3 -> 1 -> 2 .

    • dfs(vertex3, vertex3, count) ,它给你循环 3 -> 1 -> 2 -> 3 .

    所以你要多次计算同一个周期 .

    我能想到的最简单的解决方法是在 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];
    }
    

相关问题