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 -> 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
  
int t, n, m, a;
  
// Stack to store the
// visited vertices in
// the Topological Sort
stack<int> s;
  
// Store Topological Order
vector<int> tsort;
  
// Adjacency list to store edges
vector<int> adj[int(1e5) + 1];
  
// To ensure visited vertex
vector<int> visited(int(1e5) + 1);
  
// Function to perform DFS
void 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 not
bool check_cycle()
{
    // Stores the position of
    // vertex in topological order
    unordered_map<int, int> pos;
    int ind = 0;
  
    // Pop all elements from stack
    while (!s.empty()) {
        pos[s.top()] = ind;
  
        // Push element to get
        // Topological Order
        tsort.push_back(s.top());
  
        ind += 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 to v
void addEdge(int u, int v)
{
    adj[u].push_back(v);
}
  
// Driver Code
int 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;
}

chevron_right


Output:

Yes

Time Complexity: O(N + M)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.