Detect cycle in Directed Graph using Topological Sort - GeeksforGeeks

21 Dec, 2021
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 -> V from vertex U to vertex V, U comes before V in the ordering.  
Examples: 
Input: N = 4, M = 6, Edges[][] = {{0, 1}, {1, 2}, {2, 0}, {0, 2}, {2, 3}, {3, 3}} Output: Yes Explanation: A cycle 0 -> 2 -> 0 exists in the given graph
Input: N = 4, M = 3, Edges[][] = {{0, 1}, {1, 2}, {2, 3}, {0, 2}} Output: No 
Approach: In Topological Sort, the idea is to visit the parent node followed by the child node. If the given graph contains a cycle, then there is at least one node which is a parent as well as a child so this will break Topological Order. Therefore, after the topological sort, check for every directed edge whether it follows the order or not.
Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ Program to implement// the above approach#include <bits/stdc++.h>using namespace std; // n -> is number of edges in graph// m -> is number of node in graphint   n, m ; // Stack to store the// visited vertices in// the Topological Sortstack<int> s; // Store Topological Ordervector<int> tsort; // Adjacency list to store edgesvector<int> adj[int(1e5) + 1]; // To ensure visited vertexvector<int> visited(int(1e5) + 1); // Function to perform DFSvoid dfs(int u){    // Set the vertex as visited    visited[u] = 1;     for (auto it : adj[u]) {         // Visit connected vertices        if (visited[it] == 0)            dfs(it);    }     // Push into the stack on    // complete visit of vertex    s.push(u);} // Function to check and return// if a cycle exists or notbool check_cycle(){    // Stores the position of    // vertex in topological order    unordered_map<int, int> pos;    int index = 0;     // Pop all elements from stack    while (!s.empty()) {        pos[s.top()] = index;         // Push element to get        // Topological Order        tsort.push_back(s.top());         index += 1;         // Pop from the stack        s.pop();    }     for (int i = 0; i < n; i++) {        for (auto it : adj[i]) {             // If parent vertex            // does not appear first            if (pos[i] > pos[it]) {                 // Cycle exists                return true;            }        }    }     // Return false if cycle    // does not exist    return false;} // Function to add edges// from u -> vvoid addEdge(int u, int v){    adj[u].push_back(v);} // Driver Codeint main(){    n = 4, m = 5;     // Insert edges    addEdge(0, 1);    addEdge(0, 2);    addEdge(1, 2);    addEdge(2, 0);    addEdge(2, 3);     for (int i = 0; i < n; i++) {        if (visited[i] == 0) {            dfs(i);        }    }     // If cycle exist    if (check_cycle())        cout << "Yes";    else        cout << "No";     return 0;}
// Java program to implement// the above approachimport java.util.*; class GFG{     static int t, n, m, a; // Stack to store the// visited vertices in// the Topological Sortstatic Stack<Integer> s; // Store Topological Orderstatic ArrayList<Integer> tsort; // Adjacency list to store edgesstatic ArrayList<ArrayList<Integer>> adj; // To ensure visited vertexstatic int[] visited = new int[(int)1e5 + 1]; // Function to perform DFSstatic void dfs(int u){         // Set the vertex as visited    visited[u] = 1;     for(Integer it : adj.get(u))    {                 // Visit connected vertices        if (visited[it] == 0)            dfs(it);    }         // Push into the stack on    // complete visit of vertex    s.push(u);} // Function to check and return// if a cycle exists or notstatic boolean check_cycle(){         // Stores the position of    // vertex in topological order    Map<Integer, Integer> pos = new HashMap<>();         int ind = 0;         // Pop all elements from stack    while (!s.isEmpty())    {        pos.put(s.peek(), ind);                 // Push element to get        // Topological Order        tsort.add(s.peek());         ind += 1;                 // Pop from the stack        s.pop();    }     for(int i = 0; i < n; i++)    {        for(Integer it : adj.get(i))        {                         // If parent vertex            // does not appear first            if (pos.get(i) > pos.get(it))            {                                 // Cycle exists                return true;            }        }    }     // Return false if cycle    // does not exist    return false;} // Function to add edges// from u to vstatic void addEdge(int u, int v){    adj.get(u).add(v);} // Driver code   public static void main (String[] args){    n = 4; m = 5;         s = new Stack<>();    adj = new ArrayList<>();    tsort = new ArrayList<>();         for(int i = 0; i < 4; i++)        adj.add(new ArrayList<>());             // Insert edges    addEdge(0, 1);    addEdge(0, 2);    addEdge(1, 2);    addEdge(2, 0);    addEdge(2, 3);         for(int i = 0; i < n; i++)    {        if (visited[i] == 0)        {            dfs(i);        }    }         // If cycle exist    if (check_cycle())       System.out.println("Yes");    else       System.out.println("No");}} // This code is contributed by offbeat
# Python3 program to implement# the above approacht = 0n = 0m = 0a = 0  # Stack to store the# visited vertices in# the Topological Sorts = []  # Store Topological Ordertsort = []  # Adjacency list to store edgesadj = [[] for i in range(100001)]  # To ensure visited vertexvisited = [False for i in range(100001)]  # Function to perform DFSdef dfs(u):     # Set the vertex as visited    visited[u] = 1         for it in adj[u]:         # Visit connected vertices        if (visited[it] == 0):            dfs(it)      # Push into the stack on    # complete visit of vertex    s.append(u) # Function to check and return# if a cycle exists or notdef check_cycle():     # Stores the position of    # vertex in topological order    pos = dict()         ind = 0         # Pop all elements from stack    while (len(s) != 0):        pos[s[-1]] = ind          # Push element to get        # Topological Order        tsort.append(s[-1])          ind += 1          # Pop from the stack        s.pop()         for i in range(n):        for it in adj[i]:            first = 0 if i not in pos else pos[i]            second = 0 if it not in pos else pos[it]             # If parent vertex            # does not appear first            if (first > second):                  # Cycle exists                return True      # Return false if cycle    # does not exist    return False # Function to add edges# from u to vdef addEdge(u, v):         adj[u].append(v) # Driver Codeif __name__ == "__main__":         n = 4    m = 5      # Insert edges    addEdge(0, 1)    addEdge(0, 2)    addEdge(1, 2)    addEdge(2, 0)    addEdge(2, 3)         for i in range(n):        if (visited[i] == False):            dfs(i)      # If cycle exist    if (check_cycle()):        print('Yes')    else:        print('No')         # This code is contributed by rutvik_56
// C# program to implement// the above approachusing System;using System.Collections;using System.Collections.Generic;  class GFG{ static int n;  // Stack to store the// visited vertices in// the Topological Sortstatic Stack<int> s;  // Store Topological Orderstatic ArrayList tsort;  // Adjacency list to store edgesstatic ArrayList adj;  // To ensure visited vertexstatic int[] visited = new int[100001];  // Function to perform DFSstatic void dfs(int u){         // Set the vertex as visited    visited[u] = 1;      foreach(int it in (ArrayList)adj[u])    {                 // Visit connected vertices        if (visited[it] == 0)            dfs(it);    }          // Push into the stack on    // complete visit of vertex    s.Push(u);}  // Function to check and return// if a cycle exists or notstatic bool check_cycle(){         // Stores the position of    // vertex in topological order    Dictionary<int,               int> pos = new Dictionary<int,                                         int>();          int ind = 0;          // Pop all elements from stack    while (s.Count != 0)    {        pos.Add(s.Peek(), ind);                 // Push element to get        // Topological Order        tsort.Add(s.Peek());          ind += 1;                  // Pop from the stack        s.Pop();    }      for(int i = 0; i < n; i++)    {        foreach(int it in (ArrayList)adj[i])        {                         // If parent vertex            // does not appear first            if (pos[i] > pos[it])            {                                 // Cycle exists                return true;            }        }    }      // Return false if cycle    // does not exist    return false;}  // Function to add edges// from u to vstatic void addEdge(int u, int v){    ((ArrayList)adj[u]).Add(v);}  // Driver code   public static void Main(string[] args){    n = 4;          s = new Stack<int>();    adj = new ArrayList();    tsort = new ArrayList();          for(int i = 0; i < 4; i++)        adj.Add(new ArrayList());              // Insert edges    addEdge(0, 1);    addEdge(0, 2);    addEdge(1, 2);    addEdge(2, 0);    addEdge(2, 3);          for(int i = 0; i < n; i++)    {        if (visited[i] == 0)        {            dfs(i);        }    }          // If cycle exist    if (check_cycle())       Console.WriteLine("Yes");    else       Console.WriteLine("No");}} // This code is contributed by pratham76
<script> // JavaScript Program to implement// the above approach var t, n, m, a; // Stack to store the// visited vertices in// the Topological Sortvar s = []; // Store Topological Ordervar tsort = []; // Adjacency list to store edgesvar adj = Array.from(Array(100001), ()=>Array()); // To ensure visited vertexvar visited = Array(100001).fill(0); //( Function to perform )DFSfunction dfs(u){    // Set the vertex as visited    visited[u] = 1;     adj[u].forEach(it => {                  // Visit connected vertices        if (visited[it] == 0)            dfs(it);    });     // Push into the stack on    // complete visit of vertex    s.push(u);} // Function to check and return// if a cycle exists or notfunction check_cycle(){    // Stores the position of    // vertex in topological order    var pos = new Map();    var ind = 0;     // Pop all elements from stack    while (s.length!=0) {        pos.set(s[s.length-1], ind);         // Push element to get        // Topological Order        tsort.push(s[s.length-1]);         ind += 1;         // Pop from the stack        s.pop();    }    var ans = false;    for (var i = 0; i < n; i++) {        adj[i].forEach(it => {                         // If parent vertex            // does not appear first            if ((pos.has(i)?pos.get(i):0) >            (pos.has(it)?pos.get(it):0))            {                 // Cycle exists                ans = true;            }        });    };     // Return false if cycle    // does not exist    return ans;} // Function to add edges// from u to vfunction addEdge(u, v){    adj[u].push(v);} // Driver Code n = 4, m = 5; // Insert edgesaddEdge(0, 1);addEdge(0, 2);addEdge(1, 2);addEdge(2, 0);addEdge(2, 3);for (var i = 0; i < n; i++) {    if (visited[i] == 0) {        dfs(i);    }}// If cycle existif (check_cycle())    document.write( "Yes");else    document.write( "No");  </script>
Yes
 
Time Complexity: O(N + M) Auxiliary Space: O(N) 
offbeat
rutvik_56
pratham76
itsok
satyapsr13
DFS
Graph Traversals
Topological Sorting
Graph
Recursion
Searching
Sorting
Searching
Recursion
DFS
Sorting
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Topological Sorting
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Ford-Fulkerson Algorithm for Maximum Flow Problem
Write a program to print all permutations of a given string
Given an array A[] and a number x, check for pair in A[] with sum as x (aka Two Sum)
Recursion
Program for Tower of Hanoi
Program for Sum of the digits of a given number