Detect cycle in an undirected graph in C++

Introduction:

Graphs are a fundamental data structure used to model relationships between entities. Detecting cycles in a graph is a common problem in computer science and is crucial for various applications, such as network routing and resource allocation.

Undirected Graphs:

An undirected graph consists of a set of vertices and a set of edges, where each edge connects two vertices. In an undirected graph, the edges have no direction, meaning the connection between two vertices is bidirectional. Detecting cycles in such a graph involves identifying a sequence of vertices where the first and last vertices are the same.

Algorithm - Depth-First Search (DFS):

One of the widely used algorithms for detecting cycles in an undirected graph is Depth-First Search (DFS). The basic idea is to perform a depth-first traversal of the graph, marking each visited vertex.

Algorithm Steps:

  1. Start DFS from any node.
  2. Mark the current node as visited.
  3. For each neighbour of the current node:
    • If the neighbour is not visited, repeat steps a-c recursively.
    • If the neighbour is visited and is not the parent of the current node, a cycle is detected.

DFS-based cycle detection is based on the fact that if a visited node is encountered during DFS and it is not the parent of the current node, there is a back edge, indicating the presence of a cycle.

Illustration:

Consider the following undirected graph:

Detect cycle in an undirected graph in C++

Let's go through the steps of the DFS algorithm on this graph to detect cycles:

  • Start at node A.
  • Mark A as visited.
  • Explore B and C.
  • Move to B, mark it as visited.
  • Explore D and E.
  • Move to D, mark it as visited.
  • Explore B (already visited, but not the parent), detecting a cycle (B - D).
  • Backtrack to A.
  • Explore C (already visited, but not the parent).
  • Move to E, mark it as visited.
  • Explore D (already visited, but not the parent), detecting a cycle (D - E).
  • Backtrack to C.
  • Backtrack to A.

Implementation:

Explanation:

  • The program defines a class named Graph to represent an undirected graph. It has private member variables, vertices (number of vertices in the graph) and adjList (an adjacency list to store the edges).
  • The class includes a constructor to initialize the graph with a given number of vertices, an addEdge method to add edges between vertices, and an isCyclic method to check if the graph contains a cycle.
  • The addEdge method is used to add an edge between two vertices in the graph. It takes two parameters u and v, representing the vertices to be connected. The method adds v to the adjacency list of u and vice versa since the graph is undirected.
  • The isCyclicUtil method is a helper function for the cycle detection algorithm. It uses depth-first search (DFS) to traverse the graph and detect cycles.
  • It takes three parameters: the current vertex v, a vector of boolean values visited to keep track of visited vertices, and the parent of the current vertex. The function returns true if a cycle is detected and false otherwise.
  • The isCyclic method is the main function for checking whether the graph contains a cycle. It initializes a vector visited to keep track of visited vertices and iterates through all vertices using a loop.
  • If a vertex is not visited, it calls the isCyclicUtil function for that vertex. If isCyclicUtil returns true, indicating a cycle, the isCyclic method returns true; otherwise, it continues to the next unvisited vertex. If no cycle is found after exploring all vertices, the method returns false
  • The main function creates an instance of the Graph class with 5 vertices. It then adds edges to create a sample graph. Finally, it calls the isCyclic method and prints whether the graph contains a cycle or not based on the returned value.

Program Output:

Detect cycle in an undirected graph in C++

Union-Find:

Union-Find, also known as Disjoint Set Union (DSU), is another powerful technique for cycle detection. It is particularly useful for graphs with a large number of nodes.

Algorithm Steps:

Create a disjoint set for each node.

For each edge (u, v):

  • Find the representative (root) of the set containing u.
  • Find the representative of the set containing v.
  • If the representatives are the same, a cycle is detected.
  • Otherwise, union the sets containing u and v.

Union-Find works by maintaining disjoint sets and efficiently determining whether adding an edge creates a cycle. The union operation ensures that nodes connected by an edge belong to the same set, preventing the formation of cycles.

Explanation:

  • The program defines a UnionFind class, which is a data structure used to efficiently manage disjoint sets.
  • It consists of an array parent, where each element represents the parent of a set. The constructor initializes the parent array with -1, indicating that each element is initially its own parent.
  • The find method recursively finds the root (representative) of a set, and the unionSets method merges two sets by updating the parent of one set to point to the root of the other set.
  • The program also defines a Graph class, which represents an undirected graph. It has a member variable vertices to store the number of vertices and a vector edges to store the edges as pairs of vertices.
  • The constructor initializes the number of vertices, and the addEdge method allows adding edges to the graph.
  • The Graph class has a method called isCyclic, which uses the Union-Find algorithm to determine whether the graph contains a cycle. It iterates through the edges of the graph and for each edge, it finds the roots of the sets to which the vertices of the edge belong.
  • If the roots are the same, it means the vertices are in the same set and adding the edge would create a cycle. If the roots are different, it merges the sets using unionSets. The method returns true if it detects any cycle and false otherwise.
  • In the main function, an instance of the Graph class is created with 5 vertices. Edges are added to form a sample graph.
  • The isCyclic method is then called to check whether the graph contains a cycle. Finally, based on the result, the program outputs whether the graph contains a cycle or not.

Program Output:

Detect cycle in an undirected graph in C++

Conclusion:

In conclusion, the detection of cycles in an undirected graph is a crucial problem in computer science and graph theory, with applications in various domains such as network analysis, routing algorithms, and resource allocation. The implementation of a cycle detection algorithm in C++ is a valuable skill for programmers and software engineers, enabling them to build robust systems that can handle cyclic dependencies and prevent unintended consequences.

In the realm of algorithmic solutions, the detection of cycles in an undirected graph often involves traversing the graph using techniques like Depth-First Search (DFS) or Breadth-First Search (BFS). These algorithms play a fundamental role in identifying cycles efficiently and can be implemented in C++ with a clear understanding of graph theory principles. By successfully detecting cycles, developers can enhance the reliability and stability of their applications, preventing issues like infinite loops or unintended circular dependencies.

Furthermore, the implementation of cycle detection algorithms showcases the importance of algorithmic thinking and problem-solving skills in software development. It exemplifies how programmers can apply theoretical concepts to real-world scenarios, emphasizing the need for a strong foundation in data structures and algorithms.






Latest Courses