--- Difficulty: Medium Source: 160 Days of Problem Solving Tags: - Graph --- # ๐Ÿš€ _Day 7. Directed Graph Cycle_ ๐Ÿง  The problem can be found at the following link: [Question Link](https://www.geeksforgeeks.org/batch/gfg-160-problems/track/graph-gfg-160/problem/detect-cycle-in-a-directed-graph) > Note: Sorry for uploading late, my Final Sem exam is going on. ## ๐Ÿ’ก **Problem Description:** Given a **Directed Graph** with **V** vertices (numbered from 0 to V-1) and **E** edges, determine whether the graph contains any cycle. The graph is represented as a 2D vector `edges[][]`, where each entry `edges[i] = [u, v]` denotes an edge from vertex **u** to **v**. ## ๐Ÿ” **Example Walkthrough:** ### **Example 1:** #### **Input:** ``` V = 4, edges[][] = [[0, 1], [1, 2], [2, 3], [3, 3]] ``` #### **Output:** ``` true ``` #### **Explanation:** There is a self-loop at vertex 3 (3 -> 3) which forms a cycle. ### **Example 2:** #### **Input:** ``` V = 3, edges[][] = [[0, 1], [1, 2]] ``` #### **Output:** ``` false ``` #### **Explanation:** There is no cycle in the graph. ## ๐ŸŽฏ **My Approach:** ### **Kahnโ€™s Algorithm (BFS-based Cycle Detection)** 1. **Build the Graph and Compute In-Degrees:** - Convert the edge list into an adjacency list. - Compute the in-degree for each vertex. 2. **Initialize a Queue:** - Add all vertices with zero in-degree into a queue. 3. **Process Vertices:** - While the queue is not empty, remove a vertex and decrement the in-degree of its neighbors. - If any neighborโ€™s in-degree becomes zero, add it to the queue. - Count the number of vertices processed. 4. **Cycle Check:** - If the count of processed vertices is not equal to V, a cycle exists. ## ๐Ÿ•’ **Time and Auxiliary Space Complexity** - **Expected Time Complexity:** O(V + E), since each vertex and edge is processed once. - **Expected Auxiliary Space Complexity:** O(V + E), due to the in-degree array, adjacency list, and queue. ## ๐Ÿ“ **Solution Code** ## **Code (C)** ```c bool isCycle(struct graph *g, int n, int m) { int in[N] = {}, q[N], f = 0, r = 0, c = 0; for (int i = 0; i < n; i++) for (struct ListNode *p = g->head[i]; p; p = p->next) in[p->data]++; for (int i = 0; i < n; i++) if (!in[i]) q[r++] = i; while (f < r) { int u = q[f++]; c++; for (struct ListNode *p = g->head[u]; p; p = p->next) if (--in[p->data] == 0) q[r++] = p->data; } return c != n; } ``` ## **Code (C++)** ```cpp class Solution { public: bool isCyclic(int V, vector>& edges) { vector> g(V); vector in(V); for (auto& e : edges) g[e[0]].push_back(e[1]), in[e[1]]++; queue q; for (int i = 0; i < V; i++) if (!in[i]) q.push(i); int c = 0; while (!q.empty()) { int u = q.front(); q.pop(); c++; for (int v : g[u]) if (--in[v] == 0) q.push(v); } return c != V; } }; ```

โšก Alternative Approaches

## ๐Ÿ“Š **2๏ธโƒฃ DFS-Based Cycle Detection (Recursive)** #### **Algorithm Steps:** 1. Build an adjacency list from the edge list. 2. Use two arrays: `visited` (to mark processed nodes) and `recStack` (to track nodes in the current DFS recursion). 3. For each unvisited node, run a DFS. 4. If you reach a node that is already in the recursion stack, a cycle exists. ```cpp class Solution { bool dfs(int u, vector>& g, vector& vis, vector& recStack) { vis[u] = recStack[u] = true; for (int v : g[u]) { if (!vis[v] && dfs(v, g, vis, recStack)) return true; else if (recStack[v]) return true; } recStack[u] = false; return false; } public: bool isCyclic(int V, vector>& edges) { vector> g(V); for (auto &e : edges) g[e[0]].push_back(e[1]); vector vis(V, false), recStack(V, false); for (int i = 0; i < V; i++) if (!vis[i] && dfs(i, g, vis, recStack)) return true; return false; } }; ``` #### ๐Ÿ“ **Complexity Analysis:** - **Time Complexity:** `O(V + E)` - **Space Complexity:** `O(V)` for recursion stack and visited tracking #### โœ… **Why This Approach?** This DFS-based method is intuitive for cycle detection and often simpler to implement, but may face recursion depth issues for very deep graphs. ## ๐Ÿ“Š **3๏ธโƒฃ DFS-Based Cycle Detection (Iterative using Stack)** #### **Algorithm Steps:** 1. Convert the edge list into an adjacency list. 2. Instead of recursion, use an explicit stack along with two marker arrays to track visited nodes and nodes currently in the stack. 3. Check for back edges indicating a cycle. ```cpp class Solution { public: bool isCyclic(int V, vector>& edges) { vector> g(V); for (auto &e : edges) g[e[0]].push_back(e[1]); vector vis(V, false), inStack(V, false); for (int i = 0; i < V; i++) { if (!vis[i]) { stack st; st.push(i); while (!st.empty()) { int u = st.top(); if (!vis[u]) { vis[u] = inStack[u] = true; } bool found = false; for (int v : g[u]) { if (!vis[v]) { st.push(v); found = true; break; } else if (inStack[v]) { return true; } } if (!found) { inStack[u] = false; st.pop(); } } } } return false; } }; ``` #### ๐Ÿ“ **Complexity Analysis:** - **Time Complexity:** `O(V + E)` - **Space Complexity:** `O(V)` #### โœ… **Why This Approach?** It avoids recursion by using an explicit stack, which is useful in environments with limited recursion depth, though the logic can be slightly more complex. ### ๐Ÿ†š **Comparison of Approaches** | **Approach** | โฑ๏ธ **Time Complexity** | ๐Ÿ—‚๏ธ **Space Complexity** | โœ… **Pros** | โš ๏ธ **Cons** | | ------------------------------- | ---------------------- | ----------------------- | ----------------------------------------------- | -------------------------------------------- | | **Kahnโ€™s Algorithm (BFS)** | ๐ŸŸข O(V + E) | ๐ŸŸก O(V + E) | Iterative; detects cycles via topological order | Requires extra space for the in-degree array | | **DFS (Recursive)** | ๐ŸŸข O(V + E) | ๐ŸŸข O(V) | Simple; intuitive for cycle detection | Risk of stack overflow on deep graphs | | **DFS (Iterative using Stack)** | ๐ŸŸข O(V + E) | ๐ŸŸข O(V) | Avoids recursion; explicit stack control | Slightly more complex to implement | โœ… **Best Choice?** - Use **Kahnโ€™s Algorithm** when you also need topological ordering or a fully iterative solution. - Use **DFS (Recursive)** for simpler implementations on smaller or moderately sized graphs. - Use **DFS (Iterative)** in environments where recursion depth is a concern.
## **Code (Java)** ```java class Solution { public boolean isCyclic(int V, int[][] edges) { List[] g = new ArrayList[V]; int[] in = new int[V]; for (int i = 0; i < V; i++) g[i] = new ArrayList<>(); for (int[] e : edges) { g[e[0]].add(e[1]); in[e[1]]++; } Queue q = new ArrayDeque<>(); for (int i = 0; i < V; i++) if (in[i] == 0) q.add(i); int c = 0; while (!q.isEmpty()) { int u = q.poll(); c++; for (int v : g[u]) if (--in[v] == 0) q.add(v); } return c != V; } } ``` ## **Code (Python)** ```python class Solution: def isCycle(self, V, edges): g = [[] for _ in range(V)] in_d = [0]*V for u, v in edges: g[u].append(v); in_d[v] += 1 q = [i for i in range(V) if in_d[i] == 0] c = 0 while q: u = q.pop(0); c += 1 for v in g[u]: in_d[v] -= 1 if in_d[v] == 0: q.append(v) return c != V ``` ## ๐ŸŽฏ **Contribution and Support:** For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: [Any Questions](https://www.linkedin.com/in/patel-hetkumar-sandipbhai-8b110525a/). Letโ€™s make this learning journey more collaborative! โญ **If you find this helpful, please give this repository a star!** โญ ---

๐Ÿ“Visitor Count