Count of Connected Components in given Graph after Removal of given Q Vertices


The number of disconnected subgraphs created by the remaining vertices in a graph following the removal of Q specified vertices is represented by the count of connected components. There are no edges linking the various components; instead, each connected component is made up of a collection of vertices connected by edges. Some vertices may become isolated as a result of the removal of the Q vertices, causing connections to fall apart and new components to form. The approach seeks to ascertain how many disconnected subgraphs there will ultimately be. Numerous applications, including network analysis, social network studies, and optimisation methods, require an understanding of the number of connected components.

Methods Used

  • Kosaraju's Algorithm

  • Matrix−Based Approach

Kosaraju's Algorithm

After deleting the Q specified vertices from a graph, Kosaraju's Algorithm is used to determine the number of linked components in the network. It uses depth−first search (DFS) in two passes. It investigates the original graph in the first pass to get a "finish time" for every vertex. In the second pass, the graph is transposed (all edges' directions are reversed) and DFS is applied to the transformed graph, beginning at the vertex with the highest finish time. The approach determines the count of linked components in the changed graph, exposing the number of disconnected subgraphs after the vertex removal by disregarding the removed Q vertices during the procedure.

Algorithm

  • To store vertices for the initial DFS pass, make an empty stack.

  • On the original graph, run the first DFS pass:

    Use DFS to explore a connected vertex's component starting from an unexplored vertex.

    When all of a vertex's surrounding vertices have been visited, Mark visits the vertex and pushes it onto the stack.

  • Reverse the direction of each edge to transpose the graph.

  • For the second DFS pass, make a boolean array to keep track of visited vertices.

  • Run the modified graph through the second DFS pass:

    Remove each vertice in turn from the stack.

    Explore a vertex's related component using DFS if it hasn't been visited or destroyed (it's not in Q). Throughout this process, Mark visited vertices.

  • Following the removal of Q vertices, the count of connected components is equal to the number of times the second DFS is called.

  • After Q vertices are removed, the procedure produces the number of connected components in the network.

Example

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

void dfs1(int vertex, vector<vector<int>>& graph, vector<bool>& visited, stack<int>& stk) {
    visited[vertex] = true;
    for (int neighbor : graph[vertex]) {
        if (!visited[neighbor])
            dfs1(neighbor, graph, visited, stk);
    }
    stk.push(vertex);
}

void dfs2(int vertex, vector<vector<int>>& transpose_graph, vector<bool>& visited) {
    visited[vertex] = true;
    for (int neighbor : transpose_graph[vertex]) {
        if (!visited[neighbor])
            dfs2(neighbor, transpose_graph, visited);
    }
}

int kosaraju(int N, vector<vector<int>>& graph, vector<vector<int>>& transpose_graph, vector<int>& Q) {
    vector<bool> visited(N + 1, false);
    stack<int> stk;

    for (int i = 1; i <= N; i++) {
        if (!visited[i])
            dfs1(i, graph, visited, stk);
    }

    fill(visited.begin(), visited.end(), false);

    for (int i = 0; i < Q.size(); i++) {
        visited[Q[i]] = true;
    }

    int count = 0;
    while (!stk.empty()) {
        int vertex = stk.top();
        stk.pop();
        if (!visited[vertex]) {
            dfs2(vertex, transpose_graph, visited);
            count++;
        }
    }

    return count;
}

int main() {
    int N = 7; 
    int M = 8; 
    int E = 2; 

    vector<vector<int>> graph(N + 1);
    vector<vector<int>> transpose_graph(N + 1);

    vector<pair<int, int>> edges = {{1, 2}, {2, 3}, {3, 1}, {2, 4}, {4, 5}, {5, 6}, {6, 4}, {7, 6}};

    for (const auto& edge : edges) {
        int u = edge.first;
        int v = edge.second;
        graph[u].push_back(v);
        transpose_graph[v].push_back(u);
    }

    vector<int> Q = {3, 4};

    int result = kosaraju(N, graph, transpose_graph, Q);
    cout << result << endl;

    return 0;
}

Output

5

Matrix−Based Approach

An adjacency matrix or an adjacency list is used to represent the graph in the matrix−based approach. The Q specified vertices are then removed from the matrix. The count of connected components is then determined by using a graph traversal algorithm like Depth−First Search (DFS) or Breadth−First Search (BFS) to the changed graph. Vertices that have been traversed are noted to prevent reprocessing. The count of connected components in the graph following the removal of Q vertices corresponds to the number of times the traversal method is run. For different graph analysis and network−related applications, this method effectively calculates the linked component count.

Algorithm

  • Use an adjacency matrix or an adjacency list to represent the graph.

  • Modified graph is produced by removing the specified Q vertices from the matrix or list.

  • Set up a variable to keep track of the connected components' number.

  • Initially iterate over each vertex in the updated graph.

  • Apply a graph traversal algorithm (DFS or BFS) from each unexplored vertex.

  • Mark the vertices that are visited during traversal to prevent reprocessing.

  • Continue the traversal until all vertices that are related to the initial vertex have been seen.

  • For each unique set of interconnected vertices discovered, increase the number of connected components by 1 in the equation.

  • To visit every vertex in the updated graph, repeat steps 5 through 8 as necessary.

  • The total number of disconnected subgraphs in the graph, after the required vertices have been removed, is represented by the connected components count's final value.

Example

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

void dfs(vector<vector<int>>& graph, vector<bool>& visited, int node) {
    visited[node] = true;
    for (int neighbor : graph[node]) {
        if (!visited[neighbor]) {
            dfs(graph, visited, neighbor);
        }
    }
}

int countReachableNodes(vector<vector<int>>& graph) {
    int N = graph.size();
    vector<bool> visited(N, false);
    int count = 0;

    for (int i = 0; i < N; ++i) {
        if (!visited[i]) {
            dfs(graph, visited, i);
            count++;
        }
    }

    return count;
}

int main() {
    // Create the graph (Adjacency List representation)
    vector<vector<int>> graph = {
        {1},
        {0, 2},
        {1},
        {4},
        {3}
    };

    int reachableNodes = countReachableNodes(graph);
    cout << "Number of nodes accessible from all other nodes: " << reachableNodes << endl;

    return 0;
}

Output

Number of nodes accessible from all other nodes: 2

Conclusion

In conclusion, a critical metric in network analysis and related domains is the number of connected components left in a graph after a certain number of vertices are removed. The Matrix−Based Approach and Kosaraju's Algorithm both offer efficient ways to calculate this count. While the Matrix−Based Approach uses graph traversal algorithms like DFS or BFS on the redesigned graph to efficiently find linked components, Kosaraju's Algorithm uses depth−first search in two passes to identify strongly connected components. Even after the removal of certain vertices, both methods produce reliable findings that help with comprehending the graph's connectivity and structural characteristics. The properties of the graph and the particular requirements of the current challenge determine the method to be used.

Updated on: 02-Aug-2023

206 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements