githubEdit

23. Length of Longest Cycle in a Graph

βœ… GFG solution to the Length of Longest Cycle in a Graph problem: find the longest cycle in a directed functional graph using iterative timestamp traversal. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

Given a directed graph with V vertices numbered from 0 to V-1 and E edges, represented as a 2D array edges[][], where each entry edges[i] = [u, v] denotes a directed edge from u to v. Each node has at most one outgoing edge (functional graph).

Your task is to find the length of the longest cycle present in the graph. If no cycle exists, return -1.

Note: A cycle is a path that starts and ends at the same vertex.

πŸ“˜ Examples

Example 1

Input: V = 7, edges[][] = [[0,5],[1,0],[2,4],[3,1],[4,6],[5,6],[6,3]]
Output: 5
Explanation: The longest cycle is 0 β†’ 5 β†’ 6 β†’ 3 β†’ 1 β†’ 0, which has length 5.

Example 2

Input: V = 8, edges[][] = [[0,1],[1,2],[2,3],[3,0],[4,1],[5,4],[6,2],[7,6]]
Output: 4
Explanation: The longest cycle is 0 β†’ 1 β†’ 2 β†’ 3 β†’ 0, which has length 4.

πŸ”’ Constraints

  • $1 \le V, E \le 10^4$

  • $0 \le \text{edges}[i][0], \text{edges}[i][1] < V$

βœ… My Approach

The optimal approach uses Iterative Timestamp Traversal β€” a technique specially suited for functional graphs (at most one outgoing edge per node):

Timestamp Traversal (Iterative)

  1. Build Next Array:

    • Since every node has at most one outgoing edge, flatten edges[][] into a nxt[] array where nxt[u] = v. Unconnected nodes have nxt[u] = -1.

  2. Initialize Visited Array:

    • Maintain a vis[] array of size V initialized to -1. Instead of a simple boolean, store the global timestamp at which each node was first visited. This lets us measure cycle lengths directly by subtraction.

  3. Traverse Each Component:

    • For every unvisited node i, record start = t (current global time) and walk the chain: assign vis[cur] = t++, then follow nxt[cur].

    • Stop when either:

      • cur == -1 β†’ reached a dead end, no cycle in this path.

      • vis[cur] != -1 β†’ revisited a node. Two sub-cases:

        • vis[cur] >= start β†’ the revisited node belongs to the current traversal, so a cycle exists. Its length is t - vis[cur].

        • vis[cur] < start β†’ the revisited node was already settled in a previous traversal; no new cycle here.

  4. Update Answer:

    • Whenever a valid cycle is detected, update ans = max(ans, t - vis[cur]).

  5. Return Result:

    • After all nodes are processed, return ans. If no cycle was ever found, ans remains -1.

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(V), as each node is visited at most once across all traversals β€” the global timestamp ensures no node is re-processed.

  • Expected Auxiliary Space Complexity: O(V), as we use a nxt[] array of size V to store the functional graph and a vis[] array of size V to record visit timestamps.

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ DFS with 3-Color Marking

πŸ’‘ Algorithm Steps:

  1. Build a nxt[] array from edges (functional graph).

  2. Color each node: 0 = unvisited, 1 = currently in DFS stack, 2 = fully processed.

  3. Track entry time (tin[]) for each node when it enters the stack.

  4. During DFS, if the next node is already colored 1 (back-edge to active stack), compute cycle length as t - tin[v].

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(V) β€” Each node is visited exactly once during DFS.

  • Auxiliary Space: πŸ’Ύ O(V) β€” Color array, tin array, and implicit recursion stack.

βœ… Why This Approach?

  • Classic back-edge detection maps naturally to cycle identification.

  • 3-color scheme clearly distinguishes unvisited, active, and done states.

  • Easy to reason about and extend for general directed graphs.


πŸ“Š 3️⃣ Topological Sort (Kahn's BFS)

πŸ’‘ Algorithm Steps:

  1. Build nxt[] and compute in-degrees for all nodes.

  2. BFS-remove all nodes with in-degree 0 iteratively β€” these nodes can never be part of a cycle.

  3. Mark them as removed. After BFS, only cycle-participating nodes remain.

  4. For each unremoved, unseen node, walk the chain counting nodes until a seen node is hit β€” that count is the cycle length.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(V) β€” BFS over all nodes + single linear pass over cycle nodes.

  • Auxiliary Space: πŸ’Ύ O(V) β€” In-degree array, removed flags, and BFS queue.

βœ… Why This Approach?

  • Completely eliminates recursion β€” safe for very large inputs.

  • Clean two-phase logic: prune non-cycle nodes first, then measure remaining cycles.

  • Ideal when the graph has a large number of tree/chain nodes leading into cycles.


πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🏷️ Timestamp Traversal

🟒 O(V)

🟒 O(V)

πŸš€ Iterative, minimal code, fastest

πŸ”§ Works only on functional graphs

🎨 3-Color DFS

🟒 O(V)

🟑 O(V) + stack

πŸ“– Intuitive, classic approach

πŸ’Ύ Recursion stack risk on large input

πŸ”„ Topological BFS

🟒 O(V)

🟑 O(V)

⭐ No recursion, clean two-phase logic

🐌 Two-pass overhead

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

⚑ Maximum performance, competitive programming

πŸ₯‡ Timestamp Traversal

β˜…β˜…β˜…β˜…β˜…

πŸ“– Readability / learning

πŸ₯ˆ 3-Color DFS

β˜…β˜…β˜…β˜…β˜†

πŸ”§ Large input / recursion-safe

πŸ₯‰ Topological BFS

β˜…β˜…β˜…β˜…β˜†

🎯 Interview setting

πŸ… Timestamp Traversal

β˜…β˜…β˜…β˜…β˜…

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated