我正在使用递归回溯来查找有向图中的循环。这个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;
使用起始节点调用上述函数:
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个周期作为输出。
我可以看到我的当前代码对已经是先前检测到的周期的一部分的每个顶点进行循环检测(例如:具有三个节点的循环为每个单独的节点提供三个循环,而这必须是一个)。我需要一些关于出了什么问题和一些修复的提示。
答案 0 :(得分: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];
}