Bird
Raised Fist0
DSA C++programming

Cycle Detection in Undirected Graph in DSA C++

Choose your learning style10 modes available
Mental Model
We want to find if there is a loop in the graph where you can start at a node and come back to it by following edges without repeating the same edge twice.
Analogy: Imagine walking in a park with paths connecting benches. If you can start at one bench, walk along paths, and return to the same bench without retracing your steps, there is a cycle.
Graph:
  1 --- 2
   \   /
    3

Edges:
1 -> 2
1 -> 3
2 -> 3

This graph has a cycle: 1 -> 2 -> 3 -> 1
Dry Run Walkthrough
Input: Graph with edges: 1-2, 1-3, 2-3
Goal: Detect if the graph contains a cycle
Step 1: Start DFS from node 1, mark node 1 as visited
Visited: {1}
Stack: [1]
Why: We begin traversal from node 1 to explore its neighbors
Step 2: Visit neighbor node 2 from node 1, mark node 2 as visited
Visited: {1, 2}
Stack: [1, 2]
Why: Explore node 2 connected to node 1
Step 3: From node 2, visit neighbor node 3, mark node 3 as visited
Visited: {1, 2, 3}
Stack: [1, 2, 3]
Why: Explore node 3 connected to node 2
Step 4: From node 3, check neighbors: node 1 and node 2. Node 1 is visited and is not parent of 3, cycle detected
Cycle found at node 3 via neighbor 1
Why: Visiting a visited node that is not the parent means a cycle exists
Result:
Cycle detected in the graph
Annotated Code
DSA C++
#include <iostream>
#include <vector>
using namespace std;

class Graph {
public:
    int V;
    vector<vector<int>> adj;

    Graph(int V) {
        this->V = V;
        adj.resize(V + 1);
    }

    void addEdge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    bool dfs(int node, int parent, vector<bool>& visited) {
        visited[node] = true; // mark current node visited
        for (int neighbor : adj[node]) {
            if (!visited[neighbor]) {
                if (dfs(neighbor, node, visited))
                    return true; // cycle found in deeper call
            } else if (neighbor != parent) {
                return true; // visited neighbor not parent means cycle
            }
        }
        return false; // no cycle found from this node
    }

    bool hasCycle() {
        vector<bool> visited(V + 1, false);
        for (int i = 1; i <= V; i++) {
            if (!visited[i]) {
                if (dfs(i, -1, visited))
                    return true; // cycle detected
            }
        }
        return false; // no cycle in any component
    }
};

int main() {
    Graph g(3);
    g.addEdge(1, 2);
    g.addEdge(1, 3);
    g.addEdge(2, 3);

    if (g.hasCycle())
        cout << "Cycle detected in the graph" << endl;
    else
        cout << "No cycle in the graph" << endl;

    return 0;
}
visited[node] = true; // mark current node visited
mark node as visited to avoid revisiting
for (int neighbor : adj[node]) {
explore all neighbors of current node
if (!visited[neighbor]) {
if neighbor not visited, continue DFS deeper
if (dfs(neighbor, node, visited)) return true;
if cycle found deeper, propagate true up
else if (neighbor != parent) return true;
if neighbor visited and not parent, cycle detected
for (int i = 1; i <= V; i++) { if (!visited[i]) { if (dfs(i, -1, visited)) return true; } }
check all disconnected components for cycles
OutputSuccess
Cycle detected in the graph
Complexity Analysis
Time: O(V + E) because we visit each vertex and edge once during DFS
Space: O(V) for the visited array and recursion stack in worst case
vs Alternative: Compared to using union-find which also runs in near O(V + E), DFS is simpler to implement and understand for cycle detection in undirected graphs
Edge Cases
Empty graph (no vertices)
No cycle detected because there are no edges
DSA C++
for (int i = 1; i <= V; i++) { if (!visited[i]) { if (dfs(i, -1, visited)) return true; } }
Graph with single vertex and no edges
No cycle detected because no edges exist
DSA C++
for (int i = 1; i <= V; i++) { if (!visited[i]) { if (dfs(i, -1, visited)) return true; } }
Graph with multiple disconnected components
All components are checked for cycles independently
DSA C++
for (int i = 1; i <= V; i++) { if (!visited[i]) { if (dfs(i, -1, visited)) return true; } }
When to Use This Pattern
When you see a problem asking if a loop exists in an undirected graph, use DFS with parent tracking to detect cycles efficiently.
Common Mistakes
Mistake: Not checking if the visited neighbor is the parent node, causing false cycle detection
Fix: Add condition to ignore the parent node when checking visited neighbors
Mistake: Not running DFS on all disconnected components, missing cycles in isolated parts
Fix: Run DFS from every unvisited node in the graph
Summary
Detects if an undirected graph contains any cycle using DFS and parent tracking.
Use when you need to know if a loop exists in any part of an undirected graph.
The key insight is that visiting a previously visited node that is not the parent means a cycle.

Practice

(1/5)
1. What is the main idea behind detecting a cycle in an undirected graph using DFS?
easy
A. If all nodes are visited once, the graph has a cycle.
B. If we visit a node that is already visited and is not the parent, a cycle exists.
C. If the graph has more edges than nodes, it must have a cycle.
D. If the graph is disconnected, it contains a cycle.

Solution

  1. Step 1: Understand DFS traversal in undirected graph

    DFS visits nodes and tracks the parent node to avoid false cycle detection.
  2. Step 2: Detect cycle condition

    If a visited node is found that is not the parent, it means a back edge exists, indicating a cycle.
  3. Final Answer:

    If we visit a node that is already visited and is not the parent, a cycle exists. -> Option B
  4. Quick Check:

    Cycle detection in undirected graph = check visited and parent [OK]
Hint: Check visited nodes excluding parent to find cycles [OK]
Common Mistakes:
  • Ignoring the parent node in cycle check
  • Assuming disconnected graph always has cycles
  • Confusing cycle detection with number of edges
2. Which of the following C++ function signatures is correct for a DFS-based cycle detection helper in an undirected graph?
easy
A. bool dfs(int node, int parent, vector& graph, vector<bool>& visited);
B. void dfs(int node, vector<int>& graph, vector<bool>& visited);
C. bool dfs(int node, vector<int>& graph, vector<int>& visited, int parent);
D. int dfs(int node, int parent, vector<int>& graph, vector<bool>& visited);

Solution

  1. Step 1: Analyze function parameters for DFS cycle detection

    We need current node, parent node, adjacency list (graph), and visited array.
  2. Step 2: Check return type and parameter types

    Return type should be bool to indicate cycle presence; graph is vector of vectors; visited is bool vector.
  3. Final Answer:

    bool dfs(int node, int parent, vector& graph, vector<bool>& visited); -> Option A
  4. Quick Check:

    Correct DFS signature includes parent and returns bool [OK]
Hint: DFS cycle helper returns bool and takes parent node [OK]
Common Mistakes:
  • Using wrong graph data type (vector<int> instead of vector)
  • Missing parent parameter
  • Wrong return type for cycle detection
3. What will be the output of the following code snippet detecting cycle in an undirected graph?
int main() {
  vector graph = {{1,2}, {0,2}, {0,1,3}, {2}};
  vector<bool> visited(4, false);
  bool hasCycle = false;
  function dfs = [&](int node, int parent) {
    visited[node] = true;
    for (int adj : graph[node]) {
      if (!visited[adj]) {
        if (dfs(adj, node)) return true;
      } else if (adj != parent) {
        return true;
      }
    }
    return false;
  };
  for (int i = 0; i < 4; i++) {
    if (!visited[i]) {
      if (dfs(i, -1)) {
        hasCycle = true;
        break;
      }
    }
  }
  cout << (hasCycle ? "Cycle Found" : "No Cycle") << endl;
  return 0;
}
medium
A. Runtime Error
B. No Cycle
C. Compilation Error
D. Cycle Found

Solution

  1. Step 1: Analyze graph structure

    Graph edges: 0-1, 0-2, 1-2, 2-3. Nodes 0,1,2 form a triangle (cycle).
  2. Step 2: Trace DFS cycle detection

    DFS visits nodes and finds back edge between 0 and 2 or 1 and 2, detecting cycle.
  3. Final Answer:

    Cycle Found -> Option D
  4. Quick Check:

    Triangle in graph means cycle detected [OK]
Hint: Triangle or more edges among nodes means cycle [OK]
Common Mistakes:
  • Ignoring back edge condition
  • Assuming no cycle if graph is connected
  • Confusing parent node with visited node
4. Identify the bug in the following cycle detection code for an undirected graph:
bool dfs(int node, int parent, vector& graph, vector<bool>& visited) {
  visited[node] = true;
  for (int adj : graph[node]) {
    if (!visited[adj]) {
      if (dfs(adj, node, graph, visited)) return true;
    } else {
      return true;
    }
  }
  return false;
}
medium
A. It returns true even if adjacent node is the parent, causing false cycle detection.
B. It does not mark nodes as visited.
C. It uses wrong data types for graph and visited.
D. It never returns false.

Solution

  1. Step 1: Review cycle detection condition

    The else block returns true if adjacent node is visited, but does not check if it is the parent.
  2. Step 2: Identify impact of missing parent check

    Returning true for parent node causes false positive cycle detection.
  3. Final Answer:

    It returns true even if adjacent node is the parent, causing false cycle detection. -> Option A
  4. Quick Check:

    Check parent node before returning true for visited adjacency [OK]
Hint: Always exclude parent node when checking visited adjacency [OK]
Common Mistakes:
  • Not checking if visited node is parent
  • Returning true too early
  • Incorrect recursion parameters
5. Given a graph with 5 nodes and edges: 0-1, 1-2, 2-3, 3-4, 4-1, which modification to the DFS cycle detection algorithm will correctly identify the cycle and also return the nodes involved in the cycle?
hard
A. Remove the parent check and mark all visited nodes as cycle nodes.
B. Use BFS instead of DFS to detect cycles and print nodes.
C. Modify DFS to store the path stack and return the cycle path when a back edge is found.
D. Count edges and nodes; if edges >= nodes, print all nodes as cycle.

Solution

  1. Step 1: Understand cycle detection with node tracking

    DFS can track the current path using a stack or vector to record nodes visited in the current recursion.
  2. Step 2: Modify DFS to return cycle path

    When a back edge is found (visited node not parent), extract nodes from the path stack to get cycle nodes.
  3. Final Answer:

    Modify DFS to store the path stack and return the cycle path when a back edge is found. -> Option C
  4. Quick Check:

    Track path in DFS to identify cycle nodes [OK]
Hint: Use path stack in DFS to retrieve cycle nodes [OK]
Common Mistakes:
  • Using BFS which doesn't track path easily
  • Ignoring parent check causing false cycles
  • Using edge count alone to identify cycle nodes
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard