Queries to check if vertices X and Y are in the same Connected Component of an Undirected Graph


Graph theory encompasses the study of connected components, which are subgraphs in an undirected graph where every pair of vertices is linked by a path, and no other vertices are connected to it.

In this article, we will delve into the utilization of the C/C++ programming language to determine if two vertices, X and Y, belong to the same connected component in an undirected graph. We will elucidate the syntax and rationale of the method before elucidating at least two diverse approaches to tackle this problem. Furthermore, we will provide concrete code examples and their corresponding outcomes for each approach.

Syntax

The provided code snippets declare three functions in C++ for graph representation. The isConnected function takes in two vertices, X and Y, and returns a boolean value indicating whether they are part of the same connected component or not. The addEdge function takes two vertices, X and Y, and creates a connection between them in the graph. The initializeGraph function takes an integer value n as input and sets up the graph with n vertices. These functions can be executed using various graph algorithms such as Depth-First Search or Breadth-First Search to check the connectedness of two vertices and to establish connections between vertices in the graph.

bool isConnected(int X, int Y)
{
   // Code to check if X and Y are in the same connected component
   // Return true if X and Y are in the same connected component, false otherwise
}

void addEdge(int X, int Y)
{
   // Code to add an edge between vertices X and Y in the graph
}
void initializeGraph(int n)
{
   // Code to initialize the graph with 'n' vertices
}

Algorithm

Step 1 − Use the initialise Graph function to initialise the graph with the specified number of vertices.

Step 2 − Using the addEdge function, add edges between vertices

Step 3 − Implement a graph traversal method to travel to every vertex that is related to a certain vertex and mark it as visited.

Step 4 − Employ the constructed graph traversal method to determine if both vertices X and Y have been visited.

Step 5 − Return true if both vertices X and Y are visited; otherwise, return false.

Approaches

  • Approach 1 − DFS is used; it is a graph traversal algorithm that iteratively visits vertices and marks them as visited in order to investigate a graph.

  • Approach 2 − Employs the Union-Find method, which uses a data structure to monitor the division of a set into distinct subgroups. It is effective in identifying the connected parts of an undirected graph.

Approach 1

In this approach, it checks if vertices X and Y are in the same connected component using DFS, we can start from vertex X and traverse the graph using DFS.

Example 1

The code conducts an evaluation to verify if two vertices, X and Y, belong to the same connected component in a graph. It employs a Depth-First Search (DFS) algorithm to traverse the graph and determine the connectedness of the vertices. The graph is depicted using an adjacency list, where the edges between the vertices are stored as a list of neighboring vertices for each vertex. The code initializes the visited array to monitor the vertices that have been explored during the DFS traversal. The DFS function is executed for vertex X, and if vertex Y is discovered to be visited during the DFS, it signifies that both X and Y are part of the same connected component. The main function sets up the graph by creating the adjacency list and adding the edges to it, and then performs several queries to verify if two vertices are in the same connected component.

#include <iostream>
#include <vector>
using namespace std;

vector<int> adjList[100005];
bool visited[100005];

void dfs(int u) {
   visited[u] = true;
   for (int v : adjList[u])
      if (!visited[v])
   dfs(v);
}

bool areVerticesInSameComponentDFS(int X, int Y, int n) {
   for (int i = 1; i <= n; i++)
      visited[i] = false;
   dfs(X);
   return visited[Y];
}

int main() {
   int n = 5;
   int m = 4;
   int edges[][2] = {{1, 2}, {2, 3}, {3, 4}, {4, 5}};
   for (int i = 0; i < m; i++) {
      int u = edges[i][0];
      int v = edges[i][1];
      adjList[u].push_back(v);
      adjList[v].push_back(u);
   }
   int q = 2;
   int queries[][2] = {{1, 4}, {2, 5}};
   for (int i = 0; i < q; i++) {
      int X = queries[i][0];
      int Y = queries[i][1];
      if (areVerticesInSameComponentDFS(X, Y, n))
         cout << "Vertices " << X << " and " << Y << " are in the same connected component." << endl;
      else
         cout << "Vertices " << X <<" and " << Y << " are not in the same connected component." << endl;
   }
   return 0;
}

Output

Vertices 1 and 4 are in the same connected component.
Vertices 2 and 5 are in the same connected component.

Approach 2

In this approach, We can first assign each vertex to a disjoint collection in order to use the Union-Find method to determine if vertices X and Y are in the same linked component. The sets holding the edge endpoints may then be combined for each edge in the graph. Finally, we may determine if vertices X and Y are members of the same set, indicating that they are related components.

Example 2

This code implements the Union-Find algorithm to check if two vertices are in the same connected component in a graph. The input is hardcoded in the form of the number of vertices n, number of edges m, and an array of edges edges[m][2], and the number of queries q and an array of queries queries[q][2]. The function merge(u, v) merges the set containing the vertex u with the set containing the vertex v. The function areVerticesInSameComponentUnionFind(X, Y) checks if the vertices X and Y are in the same connected component by finding the parent of both vertices and checking if they are equal. If they are equal, the vertices are in the same connected component, otherwise they are not. The results of the queries are printed to the console.

#include <iostream>
using namespace std;
int parent[100005];
// Function to find the parent of a set using the Union-Find algorithm
int find(int u) {
    if (parent[u] == u) {
        return u;
    }
    return find(parent[u]);
}
void merge(int u, int v) {
    int parentU = find(u); // find the parent of u
    int parentV = find(v);
    if (parentU != parentV) {
        parent[parentU] = parentV;
    }
}
bool areVerticesInSameComponentUnionFind(int X, int Y) {
    int parentX = find(X); // find the parent of X
    int parentY = find(Y); // find the parent of Y
    return parentX == parentY;
}
int main() {
    int n = 5, m = 4;
    int edges[m][2] = {{1, 2}, {2, 3}, {3, 4}, {4, 5}};
    for (int i = 1; i <= n; i++) {
        parent[i] = i;
    }
    for (int i = 0; i < m; i++) {
        int u = edges[i][0], v = edges[i][1];
        merge(u, v);
    }
    int q = 3;
    int queries[q][2] = {{1, 5}, {3, 5}, {1, 4}};
    for (int i = 0; i < q; i++) {
        int X = queries[i][0], Y = queries[i][1];
        if (areVerticesInSameComponentUnionFind(X, Y)) {
            cout << "Vertices " << X << " and " << Y << " are in the same connected component." << endl;
        } else {
            cout << "Vertices " << X << " and " << Y << " are not in the same connected component." << endl;
        }
    }
    return 0;
}

Output

Vertices 1 and 5 are in the same connected component.
Vertices 3 and 5 are in the same connected component.
Vertices 1 and 4 are in the same connected component.

Conclusion

In this code, we've covered two methods for determining if two undirected graph vertices, X and Y, are related to one another. While the second strategy employs the Union-Find algorithm to keep track of disjoint sets, the first approach traverses the graph using Depth-First Search (DFS) to mark the visited vertices.

Updated on: 21-Jul-2023

130 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements