给定图中移除 Q 个顶点后连通分量的数量


连通分量的数量表示在移除指定的Q个顶点后,图中剩余顶点所形成的非连通子图的数量。各个分量之间没有边连接;每个连通分量都由通过边连接的一组顶点组成。移除Q个顶点后,某些顶点可能会变得孤立,导致连接断裂并形成新的分量。该方法旨在确定最终将有多少个非连通子图。许多应用都需要了解连通分量的数量,包括网络分析、社交网络研究和优化算法。

使用的方法

  • Kosaraju 算法

  • 基于矩阵的方法

Kosaraju 算法

从图中删除指定的Q个顶点后,使用 Kosaraju 算法来确定网络中的连通分量数量。它使用两遍深度优先搜索 (DFS)。第一遍遍历原始图以获得每个顶点的“完成时间”。在第二遍中,图被转置(所有边的方向都反转),并且从完成时间最高的顶点开始对转置后的图应用 DFS。该方法确定了更改后的图中连通分量的数量,通过在过程中忽略已移除的Q个顶点,揭示了顶点移除后非连通子图的数量。

算法

  • 创建一个空栈来存储第一次 DFS 遍历的顶点。

  • 在原始图上运行第一次 DFS 遍历

    从一个未探索的顶点开始,使用 DFS 探索一个连通顶点的分量。

    当一个顶点的所有相邻顶点都被访问后,标记访问该顶点并将其压入栈中。

  • 反转每条边的方向以转置图。

  • 为第二次 DFS 遍历创建一个布尔数组来跟踪已访问的顶点。

  • 在修改后的图上运行第二次 DFS 遍历

    从栈中依次移除每个顶点。

    如果一个顶点尚未被访问或删除(不在Q中),则使用 DFS 探索该顶点的相关分量。在此过程中,标记已访问的顶点。

  • 移除 Q 个顶点后,连通分量的数量等于第二次 DFS 被调用的次数。

  • 移除 Q 个顶点后,该过程会生成网络中连通分量的数量。

示例

#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;
}

输出

5

基于矩阵的方法

基于矩阵的方法使用邻接矩阵或邻接表来表示图。然后,从矩阵中移除指定的 Q 个顶点。然后,通过对修改后的图使用图遍历算法(如深度优先搜索 (DFS) 或广度优先搜索 (BFS))来确定连通分量的数量。记录已遍历的顶点以避免重新处理。移除 Q 个顶点后,图中连通分量的数量对应于遍历方法运行的次数。对于不同的图分析和网络相关应用,此方法有效地计算连通分量数量。

算法

  • 使用邻接矩阵或邻接表来表示图。

  • 通过从矩阵或列表中移除指定的 Q 个顶点来生成修改后的图。

  • 设置一个变量来跟踪连通分量的数量。

  • 最初遍历更新后的图中的每个顶点。

  • 从每个未探索的顶点应用图遍历算法 (DFS 或 BFS)。

  • 标记在遍历期间访问的顶点以避免重新处理。

  • 继续遍历,直到所有与初始顶点相关的顶点都被访问。

  • 对于发现的每个独特的互连顶点集,在方程中将连通分量的数量增加 1。

  • 根据需要重复步骤 5 到 8,以访问更新后的图中的每个顶点。

  • 移除所需顶点后,图中非连通子图的总数由连通分量数量的最终值表示。

示例

#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;
}

输出

Number of nodes accessible from all other nodes: 2

结论

总之,在移除一定数量的顶点后,图中剩余的连通分量数量是网络分析和相关领域中的一个关键指标。基于矩阵的方法和 Kosaraju 算法都提供了计算此数量的有效方法。基于矩阵的方法使用 DFS 或 BFS 等图遍历算法在重新设计的图上有效地找到连通分量,而 Kosaraju 算法使用两遍深度优先搜索来识别强连通分量。即使在移除某些顶点后,这两种方法也能产生可靠的结果,有助于理解图的连接性和结构特征。选择使用哪种方法取决于图的属性和当前问题的具体要求。

更新于:2023年8月2日

323 次浏览

开启您的职业生涯

完成课程获得认证

开始
广告
© . All rights reserved.