Bird
Raised Fist0
DSA C#programming~15 mins

Cycle Detection in Undirected Graph in DSA C# - Deep Dive

Choose your learning style10 modes available
Overview - Cycle Detection in Undirected Graph
What is it?
Cycle detection in an undirected graph means finding if there is a path that starts and ends at the same vertex without repeating edges. In simple words, it checks if you can walk around the graph and come back to where you started by following connections. This is important because cycles can affect how we process or analyze networks, like social connections or road maps. Detecting cycles helps avoid problems like infinite loops or incorrect assumptions about structure.
Why it matters
Without cycle detection, programs might get stuck in endless loops when traversing graphs, or make wrong decisions about connectivity and dependencies. For example, in network routing or file system checks, missing cycles can cause failures or crashes. Detecting cycles ensures safety and correctness in many real-world systems that rely on graph structures.
Where it fits
Before learning cycle detection, you should understand what graphs are, including vertices and edges, and basic graph traversal methods like Depth-First Search (DFS) or Breadth-First Search (BFS). After mastering cycle detection, you can explore more complex graph algorithms like detecting cycles in directed graphs, finding connected components, or working with weighted graphs.
Mental Model
Core Idea
A cycle exists if you can revisit a vertex through a different path while traversing the graph without retracing the same edge.
Think of it like...
Imagine walking through a neighborhood where streets connect houses. If you can start at one house, walk through streets, and return to the same house without turning back on the same street, you found a cycle.
Graph representation:

  A
 / \
B---C

Traversal paths:
- Start at A
- Go to B
- From B to C
- From C back to A (cycle detected)

If no such path exists, no cycle.
Build-Up - 7 Steps
1
FoundationUnderstanding Undirected Graphs
🤔
Concept: Learn what an undirected graph is and how it differs from directed graphs.
An undirected graph is a set of points called vertices connected by lines called edges. Each edge connects two vertices without direction, meaning you can travel both ways. For example, if vertex A is connected to vertex B, you can go from A to B and from B to A equally.
Result
You can visualize the graph as a network where connections don't have arrows, allowing movement in both directions.
Understanding undirected graphs is essential because cycle detection depends on the ability to move back and forth along edges.
2
FoundationGraph Traversal Basics with DFS
🤔
Concept: Introduce Depth-First Search (DFS) as a way to explore all vertices and edges.
DFS starts at a chosen vertex and explores as far as possible along each branch before backtracking. It uses a stack (or recursion) to remember where to return. This method helps visit every vertex and edge systematically.
Result
You can visit all parts of the graph without missing any connections.
DFS is the backbone of many graph algorithms, including cycle detection, because it tracks the path taken.
3
IntermediateDetecting Cycles Using DFS and Parent Tracking
🤔Before reading on: Do you think revisiting any visited vertex always means a cycle? Commit to yes or no.
Concept: Use DFS with a parent pointer to detect cycles by checking if a visited vertex is not the parent of the current vertex.
When DFS visits a vertex, it marks it as visited. If it finds an adjacent vertex already visited and that vertex is not the one it came from (parent), a cycle exists. This avoids false positives from the immediate back edge.
Result
The algorithm correctly identifies cycles by ignoring the edge leading back to the parent vertex.
Knowing to track the parent vertex prevents mistaking the immediate back edge for a cycle, which is a common mistake.
4
IntermediateImplementing Cycle Detection in C#
🤔Before reading on: Do you think a recursive DFS or iterative DFS is easier for cycle detection? Commit to your answer.
Concept: Write a complete C# method using recursive DFS to detect cycles in an undirected graph.
using System; using System.Collections.Generic; class Graph { private int vertices; private List[] adjacencyList; public Graph(int v) { vertices = v; adjacencyList = new List[v]; for (int i = 0; i < v; i++) { adjacencyList[i] = new List(); } } public void AddEdge(int v, int w) { adjacencyList[v].Add(w); adjacencyList[w].Add(v); } private bool DFS(int v, bool[] visited, int parent) { visited[v] = true; foreach (int neighbor in adjacencyList[v]) { if (!visited[neighbor]) { if (DFS(neighbor, visited, v)) return true; } else if (neighbor != parent) { return true; // Cycle found } } return false; } public bool HasCycle() { bool[] visited = new bool[vertices]; for (int i = 0; i < vertices; i++) { if (!visited[i]) { if (DFS(i, visited, -1)) return true; } } return false; } } class Program { static void Main() { Graph g = new Graph(4); g.AddEdge(0, 1); g.AddEdge(1, 2); g.AddEdge(2, 0); g.AddEdge(2, 3); Console.WriteLine(g.HasCycle() ? "Cycle detected" : "No cycle"); } }
Result
Output: Cycle detected
Implementing cycle detection concretely shows how theory translates into working code and how recursion simplifies traversal.
5
IntermediateHandling Disconnected Graphs
🤔Before reading on: Do you think checking only from one vertex is enough to detect cycles in all graphs? Commit to yes or no.
Concept: Extend cycle detection to graphs that may have multiple disconnected parts by running DFS from every unvisited vertex.
Graphs can have separate groups of vertices not connected to each other. To detect cycles anywhere, we must start DFS from each unvisited vertex until all are checked. This ensures no cycle is missed in any disconnected component.
Result
Cycle detection works correctly even if the graph is not fully connected.
Recognizing disconnected components prevents false negatives in cycle detection.
6
AdvancedTime and Space Complexity Analysis
🤔Before reading on: Do you think cycle detection in undirected graphs is faster or slower than BFS traversal? Commit to your answer.
Concept: Analyze how much time and memory the cycle detection algorithm uses based on graph size.
The DFS-based cycle detection visits each vertex and edge once. For a graph with V vertices and E edges, time complexity is O(V + E). Space complexity is O(V) for the visited array and recursion stack. This is efficient for large graphs.
Result
Cycle detection runs in linear time relative to graph size, making it practical for real applications.
Understanding complexity helps predict performance and choose suitable algorithms for large datasets.
7
ExpertDetecting Cycles Using Union-Find Data Structure
🤔Before reading on: Do you think DFS is the only way to detect cycles in undirected graphs? Commit to yes or no.
Concept: Use the Union-Find (Disjoint Set) data structure to detect cycles efficiently without recursion.
Union-Find keeps track of connected components. For each edge, it checks if the two vertices belong to the same set. If yes, adding this edge creates a cycle. Otherwise, it unites the sets. This method is often faster and simpler for sparse graphs. class UnionFind { private int[] parent; private int[] rank; public UnionFind(int size) { parent = new int[size]; rank = new int[size]; for (int i = 0; i < size; i++) { parent[i] = i; rank[i] = 0; } } public int Find(int x) { if (parent[x] != x) { parent[x] = Find(parent[x]); } return parent[x]; } public bool Union(int x, int y) { int rootX = Find(x); int rootY = Find(y); if (rootX == rootY) { return false; // Cycle detected } if (rank[rootX] < rank[rootY]) { parent[rootX] = rootY; } else if (rank[rootX] > rank[rootY]) { parent[rootY] = rootX; } else { parent[rootY] = rootX; rank[rootX]++; } return true; } } class GraphUF { private int vertices; private List<(int, int)> edges; public GraphUF(int v) { vertices = v; edges = new List<(int, int)>(); } public void AddEdge(int v, int w) { edges.Add((v, w)); } public bool HasCycle() { UnionFind uf = new UnionFind(vertices); foreach (var (v, w) in edges) { if (!uf.Union(v, w)) { return true; } } return false; } } class ProgramUF { static void Main() { GraphUF g = new GraphUF(4); g.AddEdge(0, 1); g.AddEdge(1, 2); g.AddEdge(2, 0); g.AddEdge(2, 3); Console.WriteLine(g.HasCycle() ? "Cycle detected" : "No cycle"); } }
Result
Output: Cycle detected
Knowing alternative methods like Union-Find expands your toolkit and can improve efficiency in certain scenarios.
Under the Hood
Cycle detection with DFS works by marking vertices as visited and exploring neighbors recursively. When a visited vertex is found that is not the immediate parent, it means a back edge exists, forming a cycle. The Union-Find method maintains sets of connected vertices and merges them. If two vertices of an edge are already in the same set, adding that edge creates a cycle.
Why designed this way?
DFS-based detection leverages natural graph traversal and is intuitive for recursive exploration. Union-Find was designed for efficient connectivity queries, making cycle detection a byproduct of set operations. Both methods avoid redundant checks and minimize time complexity.
DFS Cycle Detection Flow:

Start Vertex
   │
   ▼
Mark visited
   │
   ▼
Explore neighbors
   ├─ If neighbor not visited -> DFS(neighbor)
   └─ If neighbor visited and not parent -> Cycle!

Union-Find Cycle Detection Flow:

For each edge (u, v):
   ├─ Find root of u
   ├─ Find root of v
   ├─ If roots same -> Cycle!
   └─ Else Union sets
Myth Busters - 3 Common Misconceptions
Quick: Does revisiting any visited vertex always mean a cycle? Commit to yes or no.
Common Belief:If DFS visits a vertex again, it means there is a cycle.
Tap to reveal reality
Reality:Revisiting the immediate parent vertex during DFS is normal and does not indicate a cycle.
Why it matters:Mistaking the parent edge for a cycle leads to false positives and incorrect algorithm results.
Quick: Can cycle detection be done by checking only one connected component? Commit to yes or no.
Common Belief:Checking cycle from any single vertex is enough for the whole graph.
Tap to reveal reality
Reality:Disconnected graphs require checking all components separately to detect cycles anywhere.
Why it matters:Ignoring disconnected parts can miss cycles, causing bugs in applications relying on full graph analysis.
Quick: Is DFS the only way to detect cycles in undirected graphs? Commit to yes or no.
Common Belief:Cycle detection must use DFS traversal.
Tap to reveal reality
Reality:Union-Find data structure provides an alternative, often more efficient, method for cycle detection.
Why it matters:Limiting to DFS can miss opportunities for optimization and simpler code in some cases.
Expert Zone
1
Cycle detection using DFS requires careful parent tracking to avoid false cycle detection from back edges.
2
Union-Find's path compression and union by rank optimizations drastically improve performance on large graphs.
3
In sparse graphs, Union-Find often outperforms DFS due to fewer recursive calls and simpler data structures.
When NOT to use
Cycle detection in undirected graphs is not suitable for directed graphs; use algorithms like Tarjan's or DFS with recursion stack for directed cycle detection. Also, for very large dynamic graphs with frequent edge additions, incremental cycle detection algorithms or Union-Find with dynamic connectivity are better.
Production Patterns
In real systems, cycle detection is used in network topology checks, deadlock detection in operating systems, and validating dependencies in package managers. Union-Find is preferred in scenarios with many union operations, like Kruskal's algorithm for minimum spanning trees.
Connections
Deadlock Detection in Operating Systems
Both detect cycles in resource allocation graphs to find circular waits.
Understanding cycle detection helps grasp how operating systems prevent processes from waiting forever.
Kruskal's Minimum Spanning Tree Algorithm
Uses Union-Find to avoid cycles while building a spanning tree.
Cycle detection is crucial to ensure the spanning tree remains acyclic and minimal.
Social Network Analysis
Cycles represent closed groups or communities in social graphs.
Detecting cycles helps identify tightly-knit groups and understand network structure.
Common Pitfalls
#1Mistaking the immediate parent vertex as a cycle during DFS.
Wrong approach:if (visited[neighbor]) return true; // Incorrect: no parent check
Correct approach:if (visited[neighbor] && neighbor != parent) return true; // Correct: check parent
Root cause:Not tracking the parent vertex leads to false cycle detection on back edges.
#2Running DFS cycle detection from only one vertex in a disconnected graph.
Wrong approach:if (DFS(0, visited, -1)) return true; // Only one start vertex
Correct approach:for each vertex v: if (!visited[v]) if (DFS(v, visited, -1)) return true;
Root cause:Assuming the graph is connected causes missed cycles in other components.
#3Using DFS cycle detection algorithm on directed graphs without modification.
Wrong approach:Using undirected cycle detection logic directly on directed graphs.
Correct approach:Use directed graph cycle detection algorithms like DFS with recursion stack or Tarjan's algorithm.
Root cause:Directed graphs require different logic because edge directions matter for cycles.
Key Takeaways
Cycle detection in undirected graphs finds if a path loops back to the start without retracing edges.
DFS with parent tracking is a simple and effective method to detect cycles by avoiding false positives from back edges.
Union-Find data structure offers an efficient alternative by managing connected components and detecting cycles during union operations.
Checking all disconnected components is necessary to ensure no cycles are missed in the entire graph.
Understanding cycle detection is foundational for many real-world applications like network analysis, deadlock detection, and graph algorithms.

Practice

(1/5)
1. What is the main idea behind detecting a cycle in an undirected graph using DFS?
easy
A. If we visit a node that is already visited and is not the parent, a cycle exists.
B. If all nodes are visited exactly once, there is a cycle.
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 keeps track of the parent node to avoid false cycle detection.
  2. Step 2: Detect cycle condition

    If during DFS, a visited node is found that is not the parent of the current node, it means a cycle exists.
  3. Final Answer:

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

    Cycle detection in undirected graph = check visited node not parent [OK]
Hint: Check visited nodes excluding parent during DFS [OK]
Common Mistakes:
  • Ignoring parent node in cycle check
  • Assuming disconnected graph always has cycle
  • Confusing cycle detection with edge count
2. Which of the following C# code snippets correctly initializes an adjacency list for an undirected graph with 3 nodes?
easy
A. var graph = new List<int>[3]; for(int i=0; i<3; i++) graph[i] = new List<int>();
B. var graph = new List<int>[3]; graph = new List<int>();
C. List<int> graph = new List<int>[3];
D. var graph = new List(); graph.Add(new List<int>());

Solution

  1. Step 1: Understand adjacency list initialization

    We need an array of lists, each list initialized separately to hold neighbors.
  2. Step 2: Check code correctness

    var graph = new List<int>[3]; for(int i=0; i<3; i++) graph[i] = new List<int>(); creates an array of List<int> and initializes each element with a new List<int>, which is correct.
  3. Final Answer:

    var graph = new List<int>[3]; for(int i=0; i<3; i++) graph[i] = new List<int>(); -> Option A
  4. Quick Check:

    Initialize array of lists with loop [OK]
Hint: Initialize each list in array separately [OK]
Common Mistakes:
  • Not initializing each list element
  • Using wrong data types for adjacency list
  • Assigning list directly to array variable
3. Consider the following C# code snippet for cycle detection in an undirected graph:
bool DFS(int node, int parent, List<int>[] graph, bool[] visited) {
    visited[node] = true;
    foreach(var neighbor in graph[node]) {
        if(!visited[neighbor]) {
            if(DFS(neighbor, node, graph, visited)) return true;
        } else if(neighbor != parent) {
            return true;
        }
    }
    return false;
}

// Graph edges: 0-1, 1-2, 2-0
// Call: DFS(0, -1, graph, visited)
What will be the output of this DFS call?
medium
A. Compilation error
B. false
C. StackOverflowException
D. true

Solution

  1. Step 1: Analyze graph structure and DFS call

    The graph has edges 0-1, 1-2, and 2-0 forming a triangle cycle. DFS starts at node 0 with parent -1.
  2. Step 2: Trace DFS for cycle detection

    DFS visits 0, then 1, then 2. When 2 checks neighbors, it finds 0 already visited and not parent, so returns true indicating cycle.
  3. Final Answer:

    true -> Option D
  4. Quick Check:

    Triangle graph cycle detected = true [OK]
Hint: Cycle if visited neighbor not parent found [OK]
Common Mistakes:
  • Ignoring parent check causing false cycle
  • Assuming no cycle in triangle graph
  • Confusing return values in recursion
4. The following C# code attempts to detect a cycle in an undirected graph but has a bug:
bool DFS(int node, int parent, List<int>[] graph, bool[] visited) {
    visited[node] = true;
    foreach(var neighbor in graph[node]) {
        if(!visited[neighbor]) {
            if(DFS(neighbor, node, graph, visited)) return true;
        } else {
            return true;
        }
    }
    return false;
}
What is the bug in this code?
medium
A. It never marks nodes as visited.
B. It returns true even if the visited neighbor is the parent node.
C. It does not traverse all neighbors.
D. It causes infinite recursion.

Solution

  1. Step 1: Review cycle detection condition

    The code returns true if a neighbor is visited, but does not check if neighbor is parent.
  2. Step 2: Identify why this causes incorrect cycle detection

    In undirected graphs, the parent node is always visited, so returning true here falsely detects a cycle.
  3. Final Answer:

    It returns true even if the visited neighbor is the parent node. -> Option B
  4. Quick Check:

    Must exclude parent node in cycle check [OK]
Hint: Exclude parent node when checking visited neighbors [OK]
Common Mistakes:
  • Missing parent check in visited condition
  • Assuming any visited neighbor means cycle
  • Not marking nodes visited before recursion
5. You have an undirected graph represented as adjacency list:
0: [1, 2]
1: [0, 3]
2: [0, 3]
3: [1, 2, 4]
4: [3]
Using DFS cycle detection, which node will first detect the cycle and why?
hard
A. Node 4, because it has only one neighbor.
B. Node 0, because it starts the DFS traversal.
C. Node 2, because it connects back to already visited node 0.
D. Node 1, because it has the smallest index among neighbors.

Solution

  1. Step 1: Understand graph structure and DFS traversal

    Assuming neighbor lists are processed in listed order, DFS starts at node 0, visits 1 (first neighbor), then 3 (from 1), then 2 (from 3).
  2. Step 2: Identify where cycle is detected

    Node 2 has neighbors 0 and 3; 0 is already visited and not parent (parent=3), so cycle is detected at node 2 first.
  3. Final Answer:

    Node 2, because it connects back to already visited node 0. -> Option C
  4. Quick Check:

    Cycle detected at node with visited neighbors not parent [OK]
Hint: Cycle detected where visited neighbors not parent found first [OK]
Common Mistakes:
  • Assuming cycle detected at start node
  • Ignoring multiple visited neighbors
  • Confusing leaf nodes with cycle detection
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