Open In App

Detect Cycle in a Directed Graph

Last Updated : 19 Jun, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given the root of a Directed graph , The task is to check whether the graph contains a cycle or not.

Examples:

Input: N = 4, E = 6

Input-Directed-Graph

Output: Yes
Explanation: The diagram clearly shows a cycle 0 -> 2 -> 0

Input: N = 4, E = 4

Input-Directed-Graph--2

Output: No
Explanation: The diagram clearly shows no cycle.

Detect Cycle in a Directed Graph using DFS:

The problem can be solved based on the following idea:

To find cycle in a directed graph we can use the Depth First Traversal (DFS) technique. It is based on the idea that there is a cycle in a graph only if there is a back edge [i.e., a node points to one of its ancestors in a DFS tree] present in the graph.

To detect a back edge, we need to keep track of the nodes visited till now and the nodes that are in the current recursion stack [i.e., the current path that we are visiting]. If during recursion, we reach a node that is already in the recursion stack, there is a cycle present in the graph.

Note: If the graph is disconnected then get the DFS forest and check for a cycle in individual trees by checking back edges.

Step-by-step algorithm:

  • Create a recursive dfs function that has the following parameters – current vertex, visited array, and recursion stack .
  • Mark the current node as visited and also mark the index in the recursion stack.
  • Iterate a loop for all the vertices and for each vertex, call the recursive function if it is not yet visited (This step is done to make sure that if there is a forest of graphs, we are checking each forest):
    • In each recursion call, Find all the adjacent vertices of the current vertex which are not visited:
      • If an adjacent vertex is already marked in the recursion stack then return true .
      • Otherwise, call the recursive function for that adjacent vertex.
    • While returning from the recursion call, unmark the current node from the recursion stack, to represent that the current node is no longer a part of the path being traced.
  • If any of the functions returns true , stop the future function calls and return true as the answer.

Illustration:

Below is the graph showing how to detect cycle in a graph using DFS:


Below is the implementation of the above approach:

C++
// A C++ Program to detect cycle in a graph
#include <bits/stdc++.h>
using namespace std;

class Graph {
    // No. of vertices
    int V;

    // Pointer to an array containing adjacency lists
    list<int>* adj;

    // Used by isCyclic()
    bool isCyclicUtil(int v, bool visited[], bool* rs);

public:
    Graph(int V);
    void addEdge(int v, int w);
    bool isCyclic();
};

Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)
{
    // Add w to v’s list.
    adj[v].push_back(w);
}

// DFS function to find if a cycle exists
bool Graph::isCyclicUtil(int v, bool visited[],
                         bool* recStack)
{
    if (visited[v] == false) {
        // Mark the current node as visited
        // and part of recursion stack
        visited[v] = true;
        recStack[v] = true;

        // Recur for all the vertices adjacent to this
        // vertex
        list<int>::iterator i;
        for (i = adj[v].begin(); i != adj[v].end(); ++i) {
            if (!visited[*i]
                && isCyclicUtil(*i, visited, recStack))
                return true;
            else if (recStack[*i])
                return true;
        }
    }

    // Remove the vertex from recursion stack
    recStack[v] = false;
    return false;
}

// Returns true if the graph contains a cycle, else false
bool Graph::isCyclic()
{
    // Mark all the vertices as not visited
    // and not part of recursion stack
    bool* visited = new bool[V];
    bool* recStack = new bool[V];
    for (int i = 0; i < V; i++) {
        visited[i] = false;
        recStack[i] = false;
    }

    // Call the recursive helper function
    // to detect cycle in different DFS trees
    for (int i = 0; i < V; i++)
        if (!visited[i]
            && isCyclicUtil(i, visited, recStack))
            return true;

    return false;
}

// Driver code
int main()
{
    // Create a graph
    Graph g(4);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 2);
    g.addEdge(2, 0);
    g.addEdge(2, 3);
    g.addEdge(3, 3);

    // Function call
    if (g.isCyclic())
        cout << "Graph contains cycle";
    else
        cout << "Graph doesn't contain cycle";
    return 0;
}
Java
// 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<>());
    }

    // Function to check if cycle exists
    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.
    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);

        // Function call
        if (graph.isCyclic())
            System.out.println("Graph contains cycle");
        else
            System.out.println("Graph doesn't "
                               + "contain cycle");
    }
}

// This code is contributed by Sagar Shah.
Python
# Python program to detect cycle
# in a graph

from collections import defaultdict


class Graph():
    def __init__(self, vertices):
        self.graph = defaultdict(list)
        self.V = vertices

    def addEdge(self, u, v):
        self.graph[u].append(v)

    def isCyclicUtil(self, v, visited, recStack):

        # Mark current node as visited and
        # adds to recursion stack
        visited[v] = True
        recStack[v] = True

        # Recur for all neighbours
        # if any neighbour is visited and in
        # recStack then graph is cyclic
        for neighbour in self.graph[v]:
            if visited[neighbour] == False:
                if self.isCyclicUtil(neighbour, visited, recStack) == True:
                    return True
            elif recStack[neighbour] == True:
                return True

        # The node needs to be popped from
        # recursion stack before function ends
        recStack[v] = False
        return False

    # Returns true if graph is cyclic else false
    def isCyclic(self):
        visited = [False] * (self.V + 1)
        recStack = [False] * (self.V + 1)
        for node in range(self.V):
            if visited[node] == False:
                if self.isCyclicUtil(node, visited, recStack) == True:
                    return True
        return False


# Driver code
if __name__ == '__main__':
    g = Graph(4)
    g.addEdge(0, 1)
    g.addEdge(0, 2)
    g.addEdge(1, 2)
    g.addEdge(2, 0)
    g.addEdge(2, 3)
    g.addEdge(3, 3)

    if g.isCyclic() == 1:
        print("Graph contains cycle")
    else:
        print("Graph doesn't contain cycle")

# Thanks to Divyanshu Mehta for contributing this code
C#
// A C# Program to detect cycle in a graph
using System;
using System.Collections.Generic;

public class Graph {

    private readonly int V;
    private readonly List<List<int> > adj;

    public Graph(int V)
    {
        this.V = V;
        adj = new List<List<int> >(V);

        for (int i = 0; i < V; i++)
            adj.Add(new List<int>());
    }

    // Function to check if cycle exists
    private bool isCyclicUtil(int i, bool[] visited,
                              bool[] 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<int> children = adj[i];

        foreach(int c in children) if (
            isCyclicUtil(c, visited, recStack)) return true;

        recStack[i] = false;

        return false;
    }

    private void addEdge(int sou, int dest)
    {
        adj[sou].Add(dest);
    }

    // Returns true if the graph contains a
    // cycle, else false
    private bool isCyclic()
    {
        // Mark all the vertices as not visited and
        // not part of recursion stack
        bool[] visited = new bool[V];
        bool[] recStack = new bool[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);

        // Function call
        if (graph.isCyclic())
            Console.WriteLine("Graph contains cycle");
        else
            Console.WriteLine("Graph doesn't "
                              + "contain cycle");
    }
}

// This code contributed by Rajput-Ji
Javascript
// A JavaScript Program to detect cycle in a graph

let V;
let adj=[];
function Graph(v)
{
    V=v;
    for (let i = 0; i < V; i++)
        adj.push([]);
}

// Function to check if cycle exists
function isCyclicUtil(i,visited,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;
        let children = adj[i];
         
        for (let c=0;c< children.length;c++)
            if (isCyclicUtil(children[c], visited, recStack))
                return true;
                 
        recStack[i] = false;
 
        return false;
}

function addEdge(source,dest)
{
    adj [source].push(dest);
}

// Returns true if the graph contains a
// cycle, else false.
function isCyclic()
{
    // Mark all the vertices as not visited and
        // not part of recursion stack
        let visited = new Array(V);
        let recStack = new Array(V);
        for(let i=0;i<V;i++)
        {
            visited[i]=false;
            recStack[i]=false;
        }
        
         
        // Call the recursive helper function to
        // detect cycle in different DFS trees
        for (let i = 0; i < V; i++)
            if (isCyclicUtil(i, visited, recStack))
                return true;
 
        return false;
}

// Driver code
Graph(4);
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 2);
addEdge(2, 0);
addEdge(2, 3);
addEdge(3, 3);

if(isCyclic())
    console.log("Graph contains cycle");
else
    console.log("Graph doesn't "
                   + "contain cycle");


// This code is contributed by patel2127

Output
Graph contains 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.

In the below article, another O(V + E) method is discussed :
Detect Cycle in a direct graph using colors

Detect Cycle in a Directed Graph using Topological Sorting:

Here we are using Kahn’s algorithm for topological sorting, if it successfully removes all vertices from the graph, it’s a DAG with no cycles. If there are remaining vertices with in-degrees greater than 0 , it indicates the presence of at least one cycle in the graph. Hence, if we are not able to get all the vertices in topological sorting then there must be at least one cycle.

Below is the implementation of the above approach:

C++
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

class Graph {
private:
    int V; // number of vertices
    vector<vector<int> > adj; // adjacency list

public:
    Graph(int V)
    {
        this->V = V;
        adj.resize(V);
    }

    void addEdge(int v, int w) { adj[v].push_back(w); }

    bool isCyclic()
    {
        vector<int> inDegree(
            V, 0); // stores in-degree of each vertex
        queue<int>
            q; // 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 (auto v : adj[u]) {
                inDegree[v]++;
            }
        }

        // enqueue vertices with 0 in-degree
        for (int u = 0; u < V; u++) {
            if (inDegree[u] == 0) {
                q.push(u);
            }
        }

        // BFS traversal
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            visited++;

            // reduce in-degree of adjacent vertices
            for (auto v : adj[u]) {
                inDegree[v]--;
                // if in-degree becomes 0, enqueue the
                // vertex
                if (inDegree[v] == 0) {
                    q.push(v);
                }
            }
        }

        return visited != V; // if not all vertices are
                             // visited, there is a cycle
    }
};

int main()
{
    Graph g(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()) {
        cout << "Graph contains cycle." << endl;
    }
    else {
        cout << "Graph does not contain cycle." << endl;
    }

    return 0;
}
Java
// Java Program to implement above approach
// 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.");
        }
    }
}
Python
from collections import deque


class Graph:
    def __init__(self, V):
        self.V = V
        self.adj = [[] for _ in range(V)]

    def addEdge(self, v, w):
        self.adj[v].append(w)

    def isCyclic(self):
        inDegree = [0] * self.V
        q = deque()
        visited = 0

        # Calculate in-degree of each vertex
        for u in range(self.V):
            for v in self.adj[u]:
                inDegree[v] += 1

        # Enqueue vertices with 0 in-degree
        for u in range(self.V):
            if inDegree[u] == 0:
                q.append(u)

        # BFS traversal
        while q:
            u = q.popleft()
            visited += 1

            # Reduce in-degree of adjacent vertices
            for v in self.adj[u]:
                inDegree[v] -= 1
                # If in-degree becomes 0, enqueue the vertex
                if inDegree[v] == 0:
                    q.append(v)

        return visited != self.V  # If not all vertices are visited, there is a cycle


# Main driver code
g = 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():
    print("Graph contains a cycle.")
else:
    print("Graph does not contain a cycle.")
# This code is contributed by Rishabh Mathur
C#
using System;
using System.Collections.Generic;

class Graph {
    private int V; // number of vertices
    private List<List<int> > adj; // adjacency list

    public Graph(int V)
    {
        this.V = V;
        adj = new List<List<int> >();
        for (int i = 0; i < V; i++) {
            adj.Add(new List<int>());
        }
    }

    public void AddEdge(int v, int w) { adj[v].Add(w); }

    public bool IsCyclic()
    {
        int[] inDegree
            = new int[V]; // stores in-degree of each vertex
        Queue<int> q
            = new Queue<int>(); // 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++) {
            foreach(var v in adj[u]) { inDegree[v]++; }
        }

        // enqueue vertices with 0 in-degree
        for (int u = 0; u < V; u++) {
            if (inDegree[u] == 0) {
                q.Enqueue(u);
            }
        }

        // BFS traversal
        while (q.Count > 0) {
            int u = q.Dequeue();
            visited++;

            // reduce in-degree of adjacent vertices
            foreach(var v in adj[u])
            {
                inDegree[v]--;
                // if in-degree becomes 0, enqueue the
                // vertex
                if (inDegree[v] == 0) {
                    q.Enqueue(v);
                }
            }
        }

        return visited != V; // if not all vertices are
                             // visited, there is a cycle
    }
}

class Program {
    static void Main()
    {
        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()) {
            Console.WriteLine("Graph contains cycle.");
        }
        else {
            Console.WriteLine(
                "Graph does not contain cycle.");
        }
    }
}

// This code is contributed by shivamgupta0987654321
Javascript
class Graph {
    constructor(V) {
        this.V = V; // number of vertices
        this.adj = new Array(V).fill(null).map(() => []); // adjacency list
    }

    addEdge(v, w) {
        this.adj[v].push(w);
    }

    isCyclic() {
        const inDegree = new Array(this.V).fill(0); // stores in-degree of each vertex
        const q = []; // queue to store vertices with 0 in-degree
        let visited = 0; // count of visited vertices

        // calculate in-degree of each vertex
        for (let u = 0; u < this.V; u++) {
            for (let v of this.adj[u]) {
                inDegree[v]++;
            }
        }

        // enqueue vertices with 0 in-degree
        for (let u = 0; u < this.V; u++) {
            if (inDegree[u] === 0) {
                q.push(u);
            }
        }

        // BFS traversal
        while (q.length > 0) {
            const u = q.shift();
            visited++;

            // reduce in-degree of adjacent vertices
            for (let v of this.adj[u]) {
                inDegree[v]--;
                // if in-degree becomes 0, enqueue the vertex
                if (inDegree[v] === 0) {
                    q.push(v);
                }
            }
        }

        return visited !== this.V; // if not all vertices are visited, there is a cycle
    }
}

// Driver code to test above methods
function main() {
    const 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()) {
        console.log("Graph contains a cycle.");
    } else {
        console.log("Graph does not contain a cycle.");
    }
}

main();

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.



Previous Article
Next Article

Similar Reads

Detect cycle in Directed Graph using Topological Sort
Given a Directed Graph consisting of N vertices and M edges and a set of Edges[][], the task is to check whether the graph contains a cycle or not using Topological sort. Topological sort of directed graph is a linear ordering of its vertices such that, for every directed edge U -&gt; V from vertex U to vertex V, U comes before V in the ordering. E
9 min read
Detect Cycle in a Directed Graph using BFS
Given a directed graph, check whether the graph contains a cycle or not. Your function should return true if the given graph contains at least one cycle, else return false. For example, the following graph contains two cycles 0-&gt;1-&gt;2-&gt;3-&gt;0 and 2-&gt;4-&gt;2, so your function must return true. Recommended: Please solve it on "PRACTICE" f
11 min read
Detect Cycle in a directed graph using colors
Given a directed graph, check whether the graph contains a cycle or not. Your function should return true if the given graph contains at least one cycle, else return false. Example: Input: n = 4, e = 6 0 -&gt; 1, 0 -&gt; 2, 1 -&gt; 2, 2 -&gt; 0, 2 -&gt; 3, 3 -&gt; 3 Output: Yes Explanation: This diagram clearly shows a cycle 0 -&gt; 2 -&gt; 0. Inpu
11 min read
What is Directed Graph? | Directed Graph meaning
A directed graph is defined as a type of graph where the edges have a direction associated with them. Characteristics of Directed Graph Directed graphs have several characteristics that make them different from undirected graphs. Here are some key characteristics of directed graphs: Directed edges: In a directed graph, edges have a direction associ
3 min read
Detect cycle in the graph using degrees of nodes of graph
Given a graph, the task is to detect a cycle in the graph using degrees of the nodes in the graph and print all the nodes that are involved in any of the cycles. If there is no cycle in the graph then print -1. Examples: Input: Output: 0 1 2 Approach: Recursively remove all vertices of degree 1. This can be done efficiently by storing a map of vert
11 min read
Print negative weight cycle in a Directed Graph
Given a weighted directed graph consisting of V vertices and E edges. The task is to print the cyclic path whose sum of weight is negative. If there is no such path present then print "-1". Input: V = 5, E = 5, Below is the graph: Here, for the given negative cycle o/p (1-&gt;2-&gt;3-&gt;4-&gt;1) ; In fig there has to be Edge from 4--&gt;1 not from
14 min read
Print Nodes which are not part of any cycle in a Directed Graph
Given a directed graph G N nodes and E Edges consisting of nodes valued [0, N – 1] and a 2D array Edges[][2] of type {u, v} that denotes a directed edge between vertices u and v. The task is to find the nodes that are not part of any cycle in the given graph G. Examples: Input: N = 4, E = 4, Edges[][2] = { {0, 2}, {0, 1}, {2, 3}, {3, 0} }Output: 1E
14 min read
Detect a negative cycle in a Graph | (Bellman Ford)
Given a directed weighted graph, the task is to find whether the given graph contains any negative-weight cycle or not. Note: A negative-weight cycle is a cycle in a graph whose edges sum to a negative value. Example: Input: Output: No Input: Output: Yes Algorithm to Find Negative Cycle in a Directed Weighted Graph Using Bellman-Ford:Initialize dis
15+ min read
Detect a negative cycle in a Graph using Shortest Path Faster Algorithm
Given a graph G consisting of nodes valued [0, N - 1], a source S, and an array Edges[][3] of type {u, v, w} that denotes that there is a directed edge between node u and v with weight w, the task is to check if there exists a negative cycle from the given source. If found to be true, then print "Yes". Otherwise, print "No". A negative cycle is a c
11 min read
Detect Cycle in Graph using DSU
Given an undirected graph, the task is to check if the graph contains a cycle or not, using DSU. Examples: Input: The following is the graph Output: YesExplanation: There is a cycle of vertices {0, 1, 2}. Recommended PracticeDetect Cycle using DSUTry It!We already have discussed an algorithm to detect cycle in directed graph. Here Union-Find Algori
13 min read
three90RightbarBannerImg