[英]How to print each cycle in a directed graph Java?
我很麻烦。 我真的不知道如何修改代码以打印找到的每个循环。 实际上,如果图形包含一个循环,则下面的代码将返回,但是我也想知道所有可能的循环是什么。
例如,下图包含三个循环0-> 2-> 0、0-> 1-> 2-> 0和3-> 3,因此您的函数必须返回true。
// A Java Program to detect cycle in a graph
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
class Graph {
private final int V;
private final List<List<Integer>> adj;
public Graph(int V)
{
this.V = V;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++)
adj.add(new LinkedList<>());
}
// This function is a variation of DFSUytil() in
// https://www.geeksforgeeks.org/archives/18212
private boolean isCyclicUtil(int i, boolean[] visited, boolean[] recStack)
{
// Mark the current node as visited and
// part of recursion stack
if (recStack[i])
return true;
if (visited[i])
return false;
visited[i] = true;
recStack[i] = true;
List<Integer> children = adj.get(i);
for (Integer c: children)
if (isCyclicUtil(c, visited, recStack))
return true;
recStack[i] = false;
return false;
}
private void addEdge(int source, int dest) {
adj.get(source).add(dest);
}
// Returns true if the graph contains a
// cycle, else false.
// This function is a variation of DFS() in
// https://www.geeksforgeeks.org/archives/18212
private boolean isCyclic()
{
// Mark all the vertices as not visited and
// not part of recursion stack
boolean[] visited = new boolean[V];
boolean[] recStack = new boolean[V];
// Call the recursive helper function to
// detect cycle in different DFS trees
for (int i = 0; i < V; i++)
if (isCyclicUtil(i, visited, recStack))
return true;
return false;
}
// Driver code
public static void main(String[] args)
{
Graph graph = new Graph(4);
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
graph.addEdge(2, 3);
graph.addEdge(3, 3);
if(graph.isCyclic())
System.out.println("Graph contains cycle");
else
System.out.println("Graph doesn't "
+ "contain cycle");
}
}
非常感谢。
编辑:之前我提到了使用dfs
代替bfs
的可能性,但是使用dfs
可能会产生非最小周期。 (例如,如果存在循环A-> B-> C-> A,并且存在循环A-> B-> A,则它可能会先找到较长的一个,而不会找到第二个,因为节点仅被访问一次)。
按照定义, elementary cycle
是一个节点不重复自身的elementary cycle
(起始节点除外),因此情况略有不同。 由于提问者(赏金@ExceptionHandler
)想要从输出中排除那些循环,因此使用bfs
解决了该问题。
对于纯(强力) elementary cycle
搜索,将需要不同的路径查找算法。
通用(又称蛮力)实施将需要以下步骤:
对于有向图g的每个节点n
找到所有路径(使用bfs
)回到n。
如果两个节点(方向相同)之间存在多条边,则在此步骤中可以忽略它们,因为算法本身应在节点而不是边上工作。 可以在步骤5中将多个边重新引入循环中。
如果找不到路径,请继续执行步骤1,并添加n + 1
每个确定的路径都是一个循环
将它们添加到循环列表中,然后继续执行步骤1和n + 1
处理完所有节点后,将找到包含所有可能循环的列表(包括排列)。 子周期不可能形成,因为每个节点在bfs
期间只能被访问一次。
在此步骤中,将先前识别的所有排列组合在一起。 每套仅考虑一个球笼。 这可以通过对节点进行排序并删除重复项来完成。
现在,已经确定了最小的一组循环并可以将其打印出来。
如果您正在寻找特定于边的循环,则用两个节点各自的边替换两个节点之间的连接。
图A->B B->C C->D D->C C->A
示例:
Step 1-3: node A
path identified: A,B,C (A->B B->C C->A)
Step 1-3: node B
path identified: B,C,A (B->C C->A A->B)
Step 1-3: node C
path identified: C,A,B (C->A A->B B->C)
path identified: C,D (C->D D->C)
Step 1-3: node D
path identified: D,C (D->C C->D)
Step 4:
Identified as identical after ordering:
Set1:
A,B,C (A->B B->C C->A)
B,C,A (B->C C->A A->B)
C,A,B (C->A A->B B->C)
Set2:
C,D (C->D D->C)
D,C (D->C C->D)
Therefore remaining cycles:
A,B,C (A->B B->C C->A)
C,D (C->D D->C)
Step 5:
Simply printing out the cycles
(Check the bracket expressions for that,
I simply added them to highlight the relevant edges).
可以在here
找到更有效的示例方法来识别基本循环,该示例直接从此answer
。 如果有人想提出更详细的解释,那么该算法的工作原理完全可以自由选择。
将主要方法修改为:
public static void main(String[] args) {
String nodes[] = new String[4];
boolean adjMatrix[][] = new boolean[4][4];
for (int i = 0; i < 4; i++) {
nodes[i] = String.valueOf((char) ('A' + i));
}
adjMatrix[0][1] = true;
adjMatrix[1][2] = true;
adjMatrix[2][3] = true;
adjMatrix[3][2] = true;
adjMatrix[2][0] = true;
ElementaryCyclesSearch ecs = new ElementaryCyclesSearch(adjMatrix, nodes);
List cycles = ecs.getElementaryCycles();
for (int i = 0; i < cycles.size(); i++) {
List cycle = (List) cycles.get(i);
for (int j = 0; j < cycle.size(); j++) {
String node = (String) cycle.get(j);
if (j < cycle.size() - 1) {
System.out.print(node + " -> ");
} else {
System.out.print(node + " -> " + cycle.get(0));
}
}
System.out.print("\n");
}
}
实现以下目标的期望输出:
A -> B -> C -> A
C -> D -> C
在here
可以找到有关该方法的详细信息的Donald B. Johnson
论文。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.