Detect Cycle in a Directed Graph

Last Updated : 14 Aug, 2026

Given a directed graph with V vertices numbered from 0 to V - 1 and E directed edges. The graph is represented using a 2D array edges[][] of size E, where each entry edges[i] = [u, v] denotes a directed edge from vertex u to vertex v.

Check whether the graph contains any cycle. Return true if there exists at least one cycle in the graph; otherwise, return false.

Examples:

Input: V = 4, edges[][] = [[0, 1], [1, 2], [2, 0], [2, 3]]

1

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

Input: V = 4, edges[][] = [[0, 1], [0, 2], [1, 2], [2, 3]]

blobid1_1761112778

Output: false
Explanation: no cycle in the graph

Try It Yourself
redirect icon

Using DFS - O(V + E) Time and O(V) Space

To detect a cycle in a directed graph, we use Depth First Search (DFS). If DFS reaches a vertex that is already present in the current DFS path, a cycle exists.

Using only visited[] is not enough. A vertex may have been visited during an earlier DFS traversal but may not be part of the current DFS path. Therefore, we also keep track of the vertices currently being explored.

For this, we use two arrays:

  • visited[]: Marks vertices that have been visited at least once.
  • recStack[]: Marks vertices that are currently present in the DFS recursion path.

If during DFS we reach a vertex whose recStack[] value is true, a cycle is found. After completely exploring all adjacent vertices of a node, we remove it from the current DFS path by setting recStack[u] = false. This ensures that recStack[] contains only the vertices that belong to the current DFS path.

C++
#include <bits/stdc++.h>
using namespace std;

bool dfs(vector<vector<int>>& adj, int u,
         vector<bool>& visited, vector<bool>& recStack) {

    // Node is already in the current DFS path
    if (recStack[u])
        return true;

    // Node is already visited
    if (visited[u])
        return false;

    visited[u] = true;
    recStack[u] = true;

    // Visit all adjacent nodes
    for (int v : adj[u]) {
        if (dfs(adj, v, visited, recStack))
            return true;
    }

    // Remove node from current DFS path
    recStack[u] = false;

    return false;
}

bool isCyclic(int V, vector<vector<int>>& edges) {

    vector<vector<int>> adj(V);

    // Create adjacency list
    for (auto& edge : edges) {
        adj[edge[0]].push_back(edge[1]);
    }

    vector<bool> visited(V, false);
    vector<bool> recStack(V, false);

    // Check all components
    for (int i = 0; i < V; i++) {
        if (!visited[i] && dfs(adj, i, visited, recStack))
            return true;
    }

    return false;
}

int main() {

    int V = 4;

    vector<vector<int>> edges = {
        {0, 1},
        {1, 2},
        {2, 0},
        {2, 3}
    };

    cout << (isCyclic(V, edges) ? "true" : "false") << endl;

    return 0;
}
Java
import java.util.ArrayList;

class GFG {

    public static boolean dfs(ArrayList<ArrayList<Integer>> adj, int u,
                       boolean[] visited, boolean[] recStack) {

        // Node is already in the current DFS path
        if (recStack[u])
            return true;

        // Node is already visited
        if (visited[u])
            return false;

        visited[u] = true;
        recStack[u] = true;

        // Visit all adjacent nodes
        for (int v : adj.get(u)) {
            if (dfs(adj, v, visited, recStack))
                return true;
        }

        // Remove node from current DFS path
        recStack[u] = false;

        return false;
    }

    public static boolean isCyclic(int V, int[][] edges) {

        ArrayList<ArrayList<Integer>> adj = new ArrayList<>();

        for (int i = 0; i < V; i++)
            adj.add(new ArrayList<>());

        // Create adjacency list
        for (int[] edge : edges) {
            adj.get(edge[0]).add(edge[1]);
        }

        boolean[] visited = new boolean[V];
        boolean[] recStack = new boolean[V];

        // Check all components
        for (int i = 0; i < V; i++) {
            if (!visited[i] && dfs(adj, i, visited, recStack))
                return true;
        }

        return false;
    }

    public static void main(String[] args) {

        int V = 4;

        int[][] edges = {
            {0, 1},
            {1, 2},
            {2, 0},
            {2, 3}
        };

        System.out.println(isCyclic(V, edges) ? "true" : "false");
    }
}
Python
def dfs(adj, u, visited, recStack):

    # Node is already in the current DFS path
    if recStack[u]:
        return True

    # Node is already visited
    if visited[u]:
        return False

    visited[u] = True
    recStack[u] = True

    # Visit all adjacent nodes
    for v in adj[u]:
        if dfs(adj, v, visited, recStack):
            return True

    # Remove node from current DFS path
    recStack[u] = False

    return False


def isCyclic(V, edges):

    adj = [[] for _ in range(V)]

    # Create adjacency list
    for edge in edges:
        adj[edge[0]].append(edge[1])

    visited = [False] * V
    recStack = [False] * V

    # Check all components
    for i in range(V):
        if not visited[i] and dfs(adj, i, visited, recStack):
            return True

    return False


if __name__ == "__main__":

    V = 4

    edges = [
        [0, 1],
        [1, 2],
        [2, 0],
        [2, 3]
    ]

    print("true" if isCyclic(V, edges) else "false")
C#
using System;
using System.Collections.Generic;

class GFG {

    public static bool dfs(List<List<int>> adj, int u,
                    bool[] visited, bool[] recStack) {

        // Node is already in the current DFS path
        if (recStack[u])
            return true;

        // Node is already visited
        if (visited[u])
            return false;

        visited[u] = true;
        recStack[u] = true;

        // Visit all adjacent nodes
        foreach (int v in adj[u]) {
            if (dfs(adj, v, visited, recStack))
                return true;
        }

        // Remove node from current DFS path
        recStack[u] = false;

        return false;
    }

    public static bool isCyclic(int V, int[,] edges) {

        List<List<int>> adj = new List<List<int>>();

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

        // Create adjacency list
        for (int i = 0; i < edges.GetLength(0); i++) {
            adj[edges[i, 0]].Add(edges[i, 1]);
        }

        bool[] visited = new bool[V];
        bool[] recStack = new bool[V];

        // Check all components
        for (int i = 0; i < V; i++) {
            if (!visited[i] && dfs(adj, i, visited, recStack))
                return true;
        }

        return false;
    }

    public static void Main() {

        int V = 4;

        int[,] edges = {
            {0, 1},
            {1, 2},
            {2, 0},
            {2, 3}
        };

        Console.WriteLine(isCyclic(V, edges) ? "true" : "false");
    }
}
JavaScript
function dfs(adj, u, visited, recStack) {

    // Node is already in the current DFS path
    if (recStack[u])
        return true;

    // Node is already visited
    if (visited[u])
        return false;

    visited[u] = true;
    recStack[u] = true;

    // Visit all adjacent nodes
    for (let v of adj[u]) {
        if (dfs(adj, v, visited, recStack))
            return true;
    }

    // Remove node from current DFS path
    recStack[u] = false;

    return false;
}

function isCyclic(V, edges) {

    let adj = Array.from({ length: V }, () => []);

    // Create adjacency list
    for (let edge of edges) {
        adj[edge[0]].push(edge[1]);
    }

    let visited = new Array(V).fill(false);
    let recStack = new Array(V).fill(false);

    // Check all components
    for (let i = 0; i < V; i++) {
        if (!visited[i] && dfs(adj, i, visited, recStack))
            return true;
    }

    return false;
}

// Driver code

    let V = 4;

    let edges = [
        [0, 1],
        [1, 2],
        [2, 0],
        [2, 3]
    ];

    console.log(isCyclic(V, edges) ? "true" : "false");

Output
true

Using Topological Sorting - O(V + E) Time and O(V) Space

A directed graph has a topological ordering only if it is acyclic. We use Kahn’s Algorithm to find this ordering and check whether all vertices can be processed.

Kahn's Algorithm uses the indegree of each vertex, which is the number of incoming edges.

  • Calculate the indegree of each vertex.
  • Add all vertices with indegree 0 to the queue.
  • Process each vertex and decrease the indegree of its adjacent vertices.
  • Add a vertex to the queue when its indegree becomes 0.
  • Count the number of processed vertices.
  • If visited == V, the graph has no cycle.
  • If visited != V, the graph contains a cycle, as some vertices cannot be processed.

Consider: V = 4, edges[][] = [[0, 1], [0, 2], [1, 2], [2, 3]]

blobid1_1761112778

There is no cycle.

Step 1: Calculate Indegree

  • Vertex: 0 1 2 3
  • Indegree: 0 1 2 1
  • Vertex 0 has indegree 0, so add it to the queue.
  • Queue = [0]
  • visited = 0

Step 2: Process Vertices

  • Process 0: indegree of 1 becomes 0 -> add 1.
  • Process 1: indegree of 2 becomes 0 -> add 2.
  • Process 2: indegree of 3 becomes 0 -> add 3.
  • Process 3: no outgoing edges.

Finally: Queue = [], visited = 4

Step 3: Check for Cycle

  • Since visited == V: 4 == 4
  • all vertices were processed successfully. Therefore, the graph does not contain a cycle.

Output: false

C++
#include <bits/stdc++.h>
using namespace std;

bool isCyclic(int V, vector<vector<int>>& edges)
{
    vector<vector<int>> adj(V);

    // Create adjacency list
    for (auto& edge : edges)
    {
        adj[edge[0]].push_back(edge[1]);
    }

    // Array to store in-degree of each vertex
    vector<int> inDegree(V, 0);

    queue<int> q;

    // Count of visited (processed) nodes
    int visited = 0;

    // Compute in-degrees of all vertices
    for (int u = 0; u < V; u++)
    {
        for (int v : adj[u])
        {
            inDegree[v]++;
        }
    }

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

    // Perform BFS (Topological Sort)
    while (!q.empty())
    {
        int u = q.front();
        q.pop();

        visited++;

        // Reduce in-degree of neighbors
        for (int v : adj[u])
        {
            inDegree[v]--;

            if (inDegree[v] == 0)
            {
                // Add to queue when in-degree becomes 0
                q.push(v);
            }
        }
    }

    // If visited nodes != total nodes, a cycle exists
    return visited != V;
}

int main()
{
    int V = 4;

    vector<vector<int>> edges = {
        {0, 1},
        {0, 2},
        {1, 2},
        {2, 3}
    };

    cout << (isCyclic(V, edges) ? "true" : "false") << endl;

    return 0;
}
Java
import java.util.Queue;
import java.util.LinkedList;
import java.util.ArrayList;

class GFG {

    public static boolean isCyclic(int V, int[][] edges)
    {
        ArrayList<ArrayList<Integer>> adj = new ArrayList<>();

        for (int i = 0; i < V; i++)
        {
            adj.add(new ArrayList<>());
        }

        // Create adjacency list
        for (int[] edge : edges)
        {
            adj.get(edge[0]).add(edge[1]);
        }

        // Array to store in-degree of each vertex
        int[] inDegree = new int[V];

        Queue<Integer> q = new LinkedList<>();

        // Count of visited (processed) nodes
        int visited = 0;

        // Compute in-degrees of all vertices
        for (int u = 0; u < V; u++)
        {
            for (int v : adj.get(u))
            {
                inDegree[v]++;
            }
        }

        // Add all vertices with in-degree 0 to the queue
        for (int u = 0; u < V; u++)
        {
            if (inDegree[u] == 0)
            {
                q.add(u);
            }
        }

        // Perform BFS (Topological Sort)
        while (!q.isEmpty())
        {
            int u = q.poll();

            visited++;

            // Reduce in-degree of neighbors
            for (int v : adj.get(u))
            {
                inDegree[v]--;

                if (inDegree[v] == 0)
                {
                    // Add to queue when in-degree becomes 0
                    q.add(v);
                }
            }
        }

        // If visited nodes != total nodes, a cycle exists
        return visited != V;
    }

    public static void main(String[] args)
    {
        int V = 4;

        int[][] edges = {
            {0, 1},
            {0, 2},
            {1, 2},
            {2, 3}
        };

        System.out.println(isCyclic(V, edges) ? "true" : "false");
    }
}
      
Python
from collections import deque

def isCyclic(V, edges):

    adj = [[] for _ in range(V)]

    # Create adjacency list
    for edge in edges:
        adj[edge[0]].append(edge[1])

    # Array to store in-degree of each vertex
    inDegree = [0] * V

    q = deque()

    # Count of visited (processed) nodes
    visited = 0

    # Compute in-degrees of all vertices
    for u in range(V):
        for v in adj[u]:
            inDegree[v] += 1

    # Add all vertices with in-degree 0 to the queue
    for u in range(V):
        if inDegree[u] == 0:
            q.append(u)

    # Perform BFS (Topological Sort)
    while q:
        u = q.popleft()

        visited += 1

        # Reduce in-degree of neighbors
        for v in adj[u]:
            inDegree[v] -= 1

            if inDegree[v] == 0:
                # Add to queue when in-degree becomes 0
                q.append(v)

    # If visited nodes != total nodes, a cycle exists
    return visited != V


if __name__ == "__main__":

    V = 4

    edges = [
        [0, 1],
        [0, 2],
        [1, 2],
        [2, 3]
    ]

    print("true" if isCyclic(V, edges) else "false")
C#
using System;
using System.Collections.Generic;

class GFG
{
    static bool isCyclic(int V, int[,] edges)
    {
        List<List<int>> adj = new List<List<int>>();

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

        // Create adjacency list
        for (int i = 0; i < edges.GetLength(0); i++)
        {
            adj[edges[i, 0]].Add(edges[i, 1]);
        }

        // Array to store in-degree of each vertex
        int[] inDegree = new int[V];

        Queue<int> q = new Queue<int>();

        // Count of visited (processed) nodes
        int visited = 0;

        // Compute in-degrees of all vertices
        for (int u = 0; u < V; u++)
        {
            foreach (int v in adj[u])
            {
                inDegree[v]++;
            }
        }

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

        // Perform BFS (Topological Sort)
        while (q.Count > 0)
        {
            int u = q.Dequeue();

            visited++;

            // Reduce in-degree of neighbors
            foreach (int v in adj[u])
            {
                inDegree[v]--;

                if (inDegree[v] == 0)
                {
                    // Add to queue when in-degree becomes 0
                    q.Enqueue(v);
                }
            }
        }

        // If visited nodes != total nodes, a cycle exists
        return visited != V;
    }

    public static void Main()
    {
        int V = 4;

        int[,] edges = {
            {0, 1},
            {0, 2},
            {1, 2},
            {2, 3}
        };

        Console.WriteLine(isCyclic(V, edges) ? "true" : "false");
    }
}
JavaScript
function isCyclic(V, edges)
{
    let adj = Array.from({ length: V }, () => []);

    // Create adjacency list
    for (let edge of edges)
    {
        adj[edge[0]].push(edge[1]);
    }

    // Array to store in-degree of each vertex
    let inDegree = new Array(V).fill(0);

    let q = [];

    // Count of visited (processed) nodes
    let visited = 0;

    // Compute in-degrees of all vertices
    for (let u = 0; u < V; u++)
    {
        for (let v of adj[u])
        {
            inDegree[v]++;
        }
    }

    // Add all vertices with in-degree 0 to the queue
    for (let u = 0; u < V; u++)
    {
        if (inDegree[u] == 0)
        {
            q.push(u);
        }
    }

    // Perform BFS (Topological Sort)
    let front = 0;

    while (front < q.length)
    {
        let u = q[front++];

        visited++;

        // Reduce in-degree of neighbors
        for (let v of adj[u])
        {
            inDegree[v]--;

            if (inDegree[v] == 0)
            {
                // Add to queue when in-degree becomes 0
                q.push(v);
            }
        }
    }

    // If visited nodes != total nodes, a cycle exists
    return visited != V;
}

// Driver code

    let V = 4;

    let edges = [
        [0, 1],
        [0, 2],
        [1, 2],
        [2, 3]
    ];

    console.log(isCyclic(V, edges) ? "true" : "false");

Output
false
Comment