Posts Directed Graph Cycle (geeksforgeeks - SDE Sheet)
Post
Cancel

Directed Graph Cycle (geeksforgeeks - SDE Sheet)

PROBLEM DESCRIPTION

Given a Directed Graph with V vertices (Numbered from 0 to V-1) and E edges, check whether it contains any cycle or not.

geeksforgeeks

SOLUTION

APPROACH 1 - USING DFS (STACK OVERFLOW FOR LARGE #NODES)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class Solution {

    public boolean isCyclic(int V, ArrayList<ArrayList<Integer>> adj) {

        boolean[] visited = new boolean[V];

        // track nodes in the current recursion path
        boolean[] path = new boolean[V];

        // Iterate over all vertices
        for (int i = 0; i < V; i++) {

            // If a cycle is found, return true
            if (isCyclicHelper(V, adj, visited, path, i)) {
                return true;
            }

        }

        // No cycle found in any DFS traversal, return false
        return false;

    }

    public boolean isCyclicHelper(int V, ArrayList<ArrayList<Integer>> adj, boolean[] visited, boolean[] path, int i) {

        // If the node is already in the current path, a cycle is detected
        if (path[i]) {
            return true;
        }

        // If the node is already visited, no need to explore again, return false
        if (visited[i]) {
            return false;
        }

        // Mark the current node as visited
        visited[i] = true;

        // Add the current node to the recursion path
        path[i] = true;

        // Check all adjacent vertices
        for (int neighbor : adj.get(i)) {

            // If any adjacent node causes a cycle, return true
            if (isCyclicHelper(V, adj, visited, path, neighbor)) {
                return true;
            }

        }

        // Remove the current node from the recursion path (backtrack)
        path[i] = false;

        // No cycle detected
        return false;

    }
}

APPROACH 2 - USING INDEGREE (ACCEPTED)

We can solve this by using Kahn's Algorithm, which is a BFS-based approach to check for cycles in a directed graph.

The idea is to track the in-degrees of all vertices, which represent how many edges point to each vertex.

We first identify vertices with zero in-degrees (i.e., no dependencies) and add them to a queue.

As we process these vertices, we reduce the in-degrees of their neighbors. If a neighbor’s in-degree becomes zero, we add it to the queue as well. If all vertices are processed without finding any vertex with a non-zero in-degree at the end, the graph is acyclic.

However, if any vertex still has a non-zero in-degree after processing, it means there is a cycle, as some vertices are dependent on each other in a circular way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Solution {

    // Kahn's Algorithm (BFS-based topological sorting)
    public boolean isCyclic(int V, ArrayList<ArrayList<Integer>> adj) {

        //in-degrees for all vertices
        int[] indegree = new int[V];

        for (int i = 0; i < V; i++) {
            for (Integer j : adj.get(i)) {
                indegree[j]++;
            }
        }

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

        // add vertices with zero in-degree
        for (int i = 0; i < V; i++) {
            if (indegree[i] == 0) {
                q.add(i);
            }
        }

        // keep removing that node from the queue
        // assume is it removed from the graph
        // that means, indegree will reduce for all its adjacent nodes (neighbors). If it becomes 0, add that neighbor
        // the expectation is that all nodes should be added eventually if the graph has no cycle
        while (!q.isEmpty()) {

            // Dequeue a vertex
            int x = q.poll();

            // Get all neighbors of the dequeued vertex
            ArrayList<Integer> neighbors = adj.get(x);

            // Decrease the in-degree of all adjacent vertices
            for (Integer n : neighbors) {

                indegree[n]--;

                // If in-degree of a neighbor becomes zero, add it to the queue
                if (indegree[n] == 0) {
                    q.add(n);
                }

            }
        }

        // Check if there are any vertices with non-zero in-degree
        // If any vertex still has a non-zero in-degree, it means a cycle exists
        for (int i = 0; i < V; i++) {
            if (indegree[i] != 0)
                return true;
        }

        // If all vertices have zero in-degree, no cycle exists
        return false;
    }
}
This post is licensed under CC BY 4.0 by the author.