給定圖中移除 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.