Given a directed graph, check whether the graph contains a cycle. Your function should return true if the given graph contains at least one cycle; otherwise, it should return false.
Example:
Input: N = 4, E = 6

Output: Yes
Explanation: The diagram clearly shows a cycle 0 -> 2 -> 0
Input: N = 4, E = 4

Output: No
Explanation: The diagram clearly shows no cycle.
Approaches For Cycle Detection
There are two approaches to detect cycles in a directed graph:
- Depth-First Search (DFS)
- Kahn's Algorithm (Topological Sorting)
1. Java Program to Detect Cycle in a Directed Graph using (DFS)
The DFS approach is a popular method for cycle detection in directed graphs. The key idea is to use a recursive function to traverse the graph and maintain two arrays: one for visited nodes and another for nodes currently in the recursion stack (or "visiting" set). If we encounter a node that is already in the recursion stack, a cycle is detected.
- visited[]: To track whether a node has been visited.
- recStack[]: To keep track of nodes currently in the recursion stack.
Graph Class: Representing the Directed Graph
Algorithm to Create a Graph
- Initialize the Graph
- Input: Number of vertices,
V. - Output: An empty graph with
Vvertices. - Steps:
- Create an adjacency list with
Vempty lists. - Initialize each list to represent the neighbors of each vertex.
- Create an adjacency list with
- Input: Number of vertices,
- Add an Edge
- Input: Source vertex
srcand destination vertexdest. - Output: Updated adjacency list with the edge added.
- Steps:
- Append the destination vertex
destto the adjacency list of the source vertexsrc.
- Append the destination vertex
- Input: Source vertex
CycleDetection Class: Detecting Cycles
Algorithm to Detect Cycles using DFS
- Depth-First Search (DFS)
- Input: Current vertex
v, arraysvisitedandrecStack, graph objectgraph. - Output:
Trueif a cycle is detected, otherwiseFalse. - Steps:
- If
recStack[v]isTrue, returnTrue(cycle detected). - If
visited[v]isTrue, returnFalse(no cycle through this vertex). - Mark
vas visited (visited[v] = True). - Add
vto the recursion stack (recStack[v] = True). - For each neighbor
nof vertexv:- Recursively call
dfs(n, visited, recStack, graph). - If the recursive call returns
True, returnTrue(cycle detected).
- Recursively call
- Remove
vfrom the recursion stack (recStack[v] = False). - Return
False(no cycle detected through this path).
- If
- Input: Current vertex
- Cycle Detection
- Input: Graph object
graph. - Output:
Trueif the graph contains a cycle, otherwiseFalse. - Steps:
- Initialize arrays
visitedandrecStacktoFalsefor all vertices. - For each vertex
vin the graph:- If
visited[v]isFalse, calldfs(v, visited, recStack, graph). - If
dfsreturnsTrue, returnTrue(cycle detected).
- If
- Return
False(no cycle detected)
- Initialize arrays
- Input: Graph object
Implementation cycle detection using DFS in Java:
import java.util.ArrayList;
import java.util.List;
// Graph class representing a directed
// graph using adjacency list
class Graph {
private final int vertices;
private final List<List<Integer>> adjList;
public Graph(int vertices) {
this.vertices = vertices;
adjList = new ArrayList<>(vertices);
for (int i = 0; i < vertices; i++) {
adjList.add(new ArrayList<>());
}
}
public void addEdge(int src, int dest) {
adjList.get(src).add(dest);
}
public List<Integer> getNeighbors(int vertex) {
return adjList.get(vertex);
}
public int getVertices() {
return vertices;
}
}
// CycleDetection class to detect cycles in the graph
class CycleDetection {
private boolean dfs(int vertex, boolean[] visited, boolean[] recStack, Graph graph) {
if (recStack[vertex]) {
return true;
}
if (visited[vertex]) {
return false;
}
visited[vertex] = true;
recStack[vertex] = true;
for (int neighbor : graph.getNeighbors(vertex)) {
if (dfs(neighbor, visited, recStack, graph)) {
return true;
}
}
recStack[vertex] = false;
return false;
}
public boolean hasCycle(Graph graph) {
int vertices = graph.getVertices();
boolean[] visited = new boolean[vertices];
boolean[] recStack = new boolean[vertices];
for (int i = 0; i < vertices; i++) {
if (!visited[i] && dfs(i, visited, recStack, graph)) {
return true;
}
}
return false;
}
}
// Main class to demonstrate the cycle detection
public class Main {
public static void main(String[] args) {
Graph graph = new Graph(4);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 0);
graph.addEdge(2, 3);
CycleDetection cycleDetection = new CycleDetection();
boolean hasCycle = cycleDetection.hasCycle(graph);
if (hasCycle) {
System.out.println("The graph contains a cycle.");
} else {
System.out.println("The graph does not contain a cycle.");
}
}
}
Output
The graph contains a cycle.
- Time Complexity: O(V + E), the Time Complexity of this method is the same as the time complexity of DFS traversal which is O(V+E).
- Auxiliary Space: O(V). To store the visited and recursion stack O(V) space is needed.
2. Java Program to Detect Cycle in a Directed Graph using Topological Sorting:
Kahn's algorithm can also be used to detect cycles. It involves calculating the in-degree (number of incoming edges) for each vertex. If at any point the number of processed vertices is less than the total number of vertices, a cycle exists.
Initialize the Graph
- Input: Number of vertices
V. - Output: An initialized graph with an adjacency list.
- Procedure:
- Create an adjacency list with
Vempty lists. - Initialize each list to represent the neighbors of each vertex.
- Create an adjacency list with
Add an Edge
- Input: Source vertex
vand destination vertexw. - Output: Updated adjacency list with the edge added.
- Procedure:
- Append the destination vertex
wto the adjacency list of the source vertexv.
- Append the destination vertex
Cycle Detection: Using Kahn's Algorithm (Topological Sorting)
Calculate In-Degree of Each Vertex
- Input: The graph represented as an adjacency list.
- Output: An array
inDegreewhereinDegree[i]is the in-degree of vertexi. - Procedure:
- Initialize an array
inDegreeof sizeVto store the in-degrees of all vertices. - Iterate over each vertex
uin the graph. - For each adjacent vertex
vofu, incrementinDegree[v]by 1.
- Initialize an array
Enqueue Vertices with 0 In-Degree
- Input: The array
inDegree. - Output: A queue
qcontaining vertices with 0 in-degree. - Procedure:
- Initialize an empty queue
q. - Iterate over each vertex
u. - If
inDegree[u]is 0, enqueueuintoq.
- Initialize an empty queue
Perform BFS and Check for Cycles
- Input: The queue
q, adjacency listadj, and arrayinDegree. - Output: A boolean value indicating if the graph contains a cycle.
- Procedure:
- Initialize a counter
visitedto count the number of visited vertices. - While the queue
qis not empty:- Dequeue a vertex
ufromq. - Increment the
visitedcounter. - For each adjacent vertex
vofu:- Decrement
inDegree[v]by 1. - If
inDegree[v]becomes 0, enqueuevintoq.
- Decrement
- Dequeue a vertex
- If the
visitedcounter is not equal to the number of verticesV, returntrue(the graph contains a cycle). - Otherwise, return
false.
- Initialize a counter
Implementation cycle detection using Topological Sorting in Java:
// Java Program to detect cycle in a graph
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
class Graph {
private int V; // number of vertices
private ArrayList<ArrayList<Integer> >
adj; // adjacency list
public Graph(int V)
{
this.V = V;
adj = new ArrayList<>(V);
for (int i = 0; i < V; i++) {
adj.add(new ArrayList<>());
}
}
public void addEdge(int v, int w) { adj.get(v).add(w); }
public boolean isCyclic()
{
int[] inDegree
= new int[V]; // stores in-degree of each vertex
Queue<Integer> q
= new LinkedList<>(); // queue to store vertices
// with 0 in-degree
int visited = 0; // count of visited vertices
// calculate in-degree of each vertex
for (int u = 0; u < V; u++) {
for (int v : adj.get(u)) {
inDegree[v]++;
}
}
// enqueue vertices with 0 in-degree
for (int u = 0; u < V; u++) {
if (inDegree[u] == 0) {
q.add(u);
}
}
// BFS traversal
while (!q.isEmpty()) {
int u = q.poll();
visited++;
// reduce in-degree of adjacent vertices
for (int v : adj.get(u)) {
inDegree[v]--;
// if in-degree becomes 0, enqueue the
// vertex
if (inDegree[v] == 0) {
q.add(v);
}
}
}
return visited != V; // if not all vertices are
// visited, there is a cycle
}
}
// Driver code
public class Main {
public static void main(String[] args)
{
Graph g = new Graph(6);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(4, 1);
g.addEdge(4, 5);
g.addEdge(5, 3);
if (g.isCyclic()) {
System.out.println("Graph contains cycle.");
}
else {
System.out.println(
"Graph does not contain cycle.");
}
}
}
Output
Graph does not contain cycle.
Time Complexity: O(V + E), the time complexity of this method is the same as the time complexity of DFS traversal which is O(V+E).
Auxiliary Space: O(V). To store the visited and recursion stack O(V) space is needed.