Detect Cycle in a directed graph using colors - GeeksforGeeks

22 Jan, 2022
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 -> 1, 0 -> 2, 1 -> 2, 2 -> 0, 2 -> 3, 3 -> 3 Output: Yes Explanation:  
This diagram clearly shows a cycle 0 -> 2 -> 0.
Input:n = 4, e = 3 0 -> 1, 0 -> 2, 1 -> 2, 2 -> 3 Output:No Explanation:  
This diagram clearly shows no cycle. 
SolutionApproach: Depth First Traversal can be used to detect cycle in a Graph. DFS for a connected graph produces a tree. There is a cycle in a graph only if there is a back edge present in the graph. A back edge is an edge that is from a node to itself (selfloop) or one of its ancestor in the tree produced by DFS. In the following graph, there are 3 back edges, marked with cross sign. It can be observed that these 3 back edges indicate 3 cycles present in the graph.
For a disconnected graph, we get the DFS forest as output. To detect cycle, we can check for cycle in individual trees by checking back edges.
Image Source: http://www.cs.yale.edu/homes/aspnes/pinewiki/DepthFirstSearch.htmlIn the previous post, we have discussed a solution that stores visited vertices in a separate array which stores vertices of the current recursion call stack.
In this post, a different solution is discussed. The solution is from CLRS book. The idea is to do DFS of a given graph and while doing traversal, assign one of the below three colours to every vertex. 
WHITE : Vertex is not processed yet. Initially, all vertices are WHITE.GRAY: Vertex is being processed (DFS for this vertex has started, but not finished which means that all descendants (in DFS tree) of this vertex are not processed yet (or this vertex is in the function call stack)BLACK : Vertex and all its descendants are processed. While doing DFS, if an edge is encountered from current vertex to a GRAY vertex, then this edge is back edge and hence there is a cycle.  
Algorithm:  
Create a recursive function that takes the edge and color array (this can be also kept as a global variable)Mark the current node as GREY.Traverse all the adjacent nodes and if any node is marked GREY then return true as a loop is bound to exist.If any adjacent vertex is WHITE then call the recursive function for that node. If the function returns true. Return true.If no adjacent node is grey or has not returned true then mark the current Node as BLACK and return false.
Create a recursive function that takes the edge and color array (this can be also kept as a global variable)
Mark the current node as GREY.
Traverse all the adjacent nodes and if any node is marked GREY then return true as a loop is bound to exist.
If any adjacent vertex is WHITE then call the recursive function for that node. If the function returns true. Return true.
If no adjacent node is grey or has not returned true then mark the current Node as BLACK and return false.
Implementation:  
C++
Java
Python3
C#
Javascript
// A DFS based approach to find if there is a cycle// in a directed graph.  This approach strictly follows// the algorithm given in CLRS book.#include <bits/stdc++.h>using namespace std; enum Color {WHITE, GRAY, BLACK}; // Graph class represents a directed graph using// adjacency list representationclass Graph{    int V; // No. of vertices    list<int>* adj; // adjacency lists     // DFS traversal of the vertices reachable from v    bool DFSUtil(int v, int color[]);public:    Graph(int V);  // Constructor     // function to add an edge to graph    void addEdge(int v, int w);     bool isCyclic();}; // ConstructorGraph::Graph(int V){    this->V = V;    adj = new list<int>[V];} // Utility function to add an edgevoid Graph::addEdge(int v, int w){    adj[v].push_back(w); // Add w to v's list.} // Recursive function to find if there is back edge// in DFS subtree tree rooted with 'u'bool Graph::DFSUtil(int u, int color[]){    // GRAY :  This vertex is being processed (DFS    //         for this vertex has started, but not    //         ended (or this vertex is in function    //         call stack)    color[u] = GRAY;     // Iterate through all adjacent vertices    list<int>::iterator i;    for (i = adj[u].begin(); i != adj[u].end(); ++i)    {        int v = *i;  // An adjacent of u         // If there is        if (color[v] == GRAY)          return true;         // If v is not processed and there is a back        // edge in subtree rooted with v        if (color[v] == WHITE && DFSUtil(v, color))          return true;    }     // Mark this vertex as processed    color[u] = BLACK;     return false;} // Returns true if there is a cycle in graphbool Graph::isCyclic(){    // Initialize color of all vertices as WHITE    int *color = new int[V];    for (int i = 0; i < V; i++)        color[i] = WHITE;     // Do a DFS traversal beginning with all    // vertices    for (int i = 0; i < V; i++)        if (color[i] == WHITE)           if (DFSUtil(i, color) == true)              return true;     return false;} // Driver code to test aboveint main(){    // Create a graph given in the above diagram    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);     if (g.isCyclic())        cout << "Graph contains cycle";    else        cout << "Graph doesn't contain cycle";     return 0;}
import java.io.*;import java.util.*; class GFG{     // A DFS based approach to find if there is a cycle    // in a directed graph. This approach strictly follows    // the algorithm given in CLRS book.    static int WHITE = 0, GRAY = 1, BLACK = 2;     // Graph class represents a directed graph using    // adjacency list representation    static class Graph    {            int V;            LinkedList<Integer>[] adjList;                         // Constructor            Graph(int ver)            {                V = ver;                adjList = new LinkedList[V];                for (int i = 0; i < V; i++)                    adjList[i] = new LinkedList<>();            }    }     // Utility function to add an edge    static void addEdge(Graph g, int u, int v)    {            g.adjList[u].add(v); // Add v to u's list.    }     // Recursive function to find if there is back edge    // in DFS subtree tree rooted with 'u'    static boolean DFSUtil(Graph g, int u, int[] color)    {            // GRAY : This vertex is being processed (DFS            // for this vertex has started, but not            // ended (or this vertex is in function            // call stack)            color[u] = GRAY;                         // Iterate through all adjacent vertices            for (Integer in : g.adjList[u])            {                // If there is                if (color[in] == GRAY)                    return true;                 // If v is not processed and there is a back                // edge in subtree rooted with v                if (color[in] == WHITE && DFSUtil(g, in, color) == true)                    return true;            }             // Mark this vertex as processed            color[u] = BLACK;            return false;    }     // Returns true if there is a cycle in graph    static boolean isCyclic(Graph g)    {            // Initialize color of all vertices as WHITE            int[] color = new int[g.V];            for (int i = 0; i < g.V; i++)            {                color[i] = WHITE;            }             // Do a DFS traversal beginning with all            // vertices            for (int i = 0; i < g.V; i++)            {                if (color[i] == WHITE)                {                    if(DFSUtil(g, i, color) == true)                        return true;                }            }            return false;     }     // Driver code to test above    public static void main(String args[])    {            // Create a graph given in the above diagram            Graph g = new Graph(4);            addEdge(g, 0, 1);            addEdge(g, 0, 2);            addEdge(g, 1, 2);            addEdge(g, 2, 0);            addEdge(g, 2, 3);            addEdge(g, 3, 3);            if (isCyclic(g))                System.out.println("Graph contains cycle");            else                System.out.println("Graph doesn't contain cycle");    }} // This code is contributed by rachana soma
# Python program to detect cycle in# a directed graph from collections import defaultdict class Graph():    def __init__(self, V):        self.V = V        self.graph = defaultdict(list)     def addEdge(self, u, v):        self.graph[u].append(v)     def DFSUtil(self, u, color):        # GRAY :  This vertex is being processed (DFS        #         for this vertex has started, but not        #         ended (or this vertex is in function        #         call stack)        color[u] = "GRAY"         for v in self.graph[u]:             if color[v] == "GRAY":                return True             if color[v] == "WHITE" and self.DFSUtil(v, color) == True:                return True         color[u] = "BLACK"        return False     def isCyclic(self):        color = ["WHITE"] * self.V         for i in range(self.V):            if color[i] == "WHITE":                if self.DFSUtil(i, color) == True:                    return True        return False # Driver program to test above functions 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)print ("Graph contains cycle" if g.isCyclic() == True\                             else "Graph doesn't contain cycle")                              # This program is contributed by Divyanshu Mehta                            
// A C# program to detect cycle in// an undirected graph using BFS.using System;using System.Collections.Generic; class GFG{     // A DFS based approach to find if    // there is a cycle in a directed graph.    // This approach strictly follows the    // algorithm given in CLRS book.    static int WHITE = 0, GRAY = 1, BLACK = 2;     // Graph class represents a directed graph    // using adjacency list representation    public class Graph    {        public int V;        public List<int>[] adjList;                 // Constructor        public Graph(int ver)        {            V = ver;            adjList = new List<int>[V];            for (int i = 0; i < V; i++)                adjList[i] = new List<int>();        }    }     // Utility function to add an edge    static void addEdge(Graph g, int u, int v)    {        g.adjList[u].Add(v); // Add v to u's list.    }     // Recursive function to find if there is back edge    // in DFS subtree tree rooted with 'u'    static bool DFSUtil(Graph g, int u, int[] color)    {        // GRAY : This vertex is being processed (DFS        // for this vertex has started, but not        // ended (or this vertex is in function        // call stack)        color[u] = GRAY;                 // Iterate through all adjacent vertices        foreach (int iN in g.adjList[u])        {            // If there is            if (color[iN] == GRAY)                return true;             // If v is not processed and there is a back            // edge in subtree rooted with v            if (color[iN] == WHITE &&                DFSUtil(g, iN, color) == true)                return true;        }         // Mark this vertex as processed        color[u] = BLACK;        return false;    }         // Returns true if there is a cycle in graph    static bool isCyclic(Graph g)    {        // Initialize color of all vertices as WHITE        int[] color = new int[g.V];        for (int i = 0; i < g.V; i++)        {            color[i] = WHITE;        }         // Do a DFS traversal beginning with all        // vertices        for (int i = 0; i < g.V; i++)        {            if (color[i] == WHITE)            {                if(DFSUtil(g, i, color) == true)                    return true;            }        }        return false;     }     // Driver Code    public static void Main(String []args)    {        // Create a graph given in the above diagram        Graph g = new Graph(4);        addEdge(g, 0, 1);        addEdge(g, 0, 2);        addEdge(g, 1, 2);        addEdge(g, 2, 0);        addEdge(g, 2, 3);        addEdge(g, 3, 3);        if (isCyclic(g))            Console.WriteLine("Graph contains cycle");        else            Console.WriteLine("Graph doesn't contain cycle");    }} // This code is contributed by PrinciRaj1992
<script> // A Javascript program to detect cycle in// an undirected graph using BFS. // A DFS based approach to find if// there is a cycle in a directed graph.// This approach strictly follows the// algorithm given in CLRS book.var WHITE = 0, GRAY = 1, BLACK = 2; // Graph class represents a directed graph// using adjacency list representationclass Graph{         // Constructor    constructor(ver)    {        this.V = ver;        this.adjList = Array.from(            Array(this.V), () => Array(this.V));    }} // Utility function to add an edgefunction addEdge(g, u, v){         // Push v to u's list.    g.adjList[u].push(v);} // Recursive function to find if there is back edge// in DFS subtree tree rooted with 'u'function DFSUtil(g, u, color){         // GRAY : This vertex is being processed (DFS    // for this vertex has started, but not    // ended (or this vertex is in function    // call stack)    color[u] = GRAY;         // Iterate through all adjacent vertices    for(var iN of g.adjList[u])    {                 // If there is        if (color[iN] == GRAY)            return true;                     // If v is not processed and there is a back        // edge in subtree rooted with v        if (color[iN] == WHITE &&            DFSUtil(g, iN, color) == true)            return true;    }         // Mark this vertex as processed    color[u] = BLACK;    return false;} // Returns true if there is a cycle in graphfunction isCyclic(g){         // Initialize color of all vertices as WHITE    var color =  Array(g.V);    for(var i = 0; i < g.V; i++)    {        color[i] = WHITE;    }         // Do a DFS traversal beginning with all    // vertices    for(var i = 0; i < g.V; i++)    {        if (color[i] == WHITE)        {            if (DFSUtil(g, i, color) == true)                return true;        }    }    return false;} // Driver Code // Create a graph given in the above diagramvar g = new Graph(4);addEdge(g, 0, 1);addEdge(g, 0, 2);addEdge(g, 1, 2);addEdge(g, 2, 0);addEdge(g, 2, 3);addEdge(g, 3, 3); if (isCyclic(g))    document.write("Graph contains cycle");else    document.write("Graph doesn't contain cycle");     // This code is contributed by rrrtnx </script>
Output: 
Graph contains cycle
Complexity Analysis: 
Time complexity: O(V + E), where V is the number of vertices and E is the number of edges in the graph.
Space Complexity :O(V). Since an extra color array is needed of size V.
YouTubeGeeksforGeeks500K subscribersDetect Cycle in a Directed graph using colors | GeeksforGeeksWatch laterShareCopy linkInfoShoppingTap to unmuteIf playback doesn't begin shortly, try restarting your device.You're signed outVideos you watch may be added to the TV's watch history and influence TV recommendations. To avoid this, cancel and sign in to YouTube on your computer.CancelConfirmMore videosMore videosSwitch cameraShareInclude playlistAn error occurred while retrieving sharing information. Please try again later.Watch on0:000:000:00 / 7:25•Live•<div class="player-unavailable"><h1 class="message">An error occurred.</h1><div class="submessage"><a href="https://www.youtube.com/watch?v=wQqFQeucFDc" target="_blank">Try watching this video on www.youtube.com</a>, or enable JavaScript if it is disabled in your browser.</div></div>
This article is contributed by Aditya Goel. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above 
rachana soma
ManasChhabra2
princiraj1992
andrew1234
rrrtnx
surinderdawra388
amartyaniel20
DFS
Graph Coloring
graph-cycle
Graph
DFS
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Dijkstra's shortest path algorithm | Greedy Algo-7
Prim’s Minimum Spanning Tree (MST) | Greedy Algo-5
Kruskal’s Minimum Spanning Tree Algorithm | Greedy Algo-2
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Traveling Salesman Problem (TSP) Implementation
Disjoint Set (Or Union-Find) | Set 1 (Detect Cycle in an Undirected Graph)
Ford-Fulkerson Algorithm for Maximum Flow Problem
Strongly Connected Components