グラフの連結成分の個数を求めるアルゴリズム
連結成分とは、「任意の2頂点間にパスが存在するような部分グラフのうち極大なもの」のことを言います。
アルゴリズム
グラフ \(G=(V,E)\) の連結成分の個数を数えるアルゴリズム:
- 「未探索」の頂点について以下を行う
- DFS or BFS で同じ連結成分に含まれる頂点を全て「探索済み」にする
- DFS or BFS を行った回数が連結成分の個数
連結成分の個数はDFSやBFSで簡単に求めることができます。1つの連結成分は、1回のDFSやBFSで探索することができるからです。
計算量
- \(O(|V|+|E|)\)
全体において各頂点が未探索かどうか調べるので \(O(|V|)\)だけかかり、DFS や BFS で各辺について調べることになるので \(O(|E|)\) の計算量になります。合わせて \(O(|V|+|E|)\) です。
C++ での実装例
頂点数 n 、辺の数 m となる無向グラフの連結成分を DFS で数えるコードです。
#include <bits/stdc++.h> using namespace std; struct Edge { int to; }; using Graph = vector<vector<Edge>>; // 深さ優先探索 vector<bool> seen; // 探索したか記録 void dfs(const Graph &G, int v) { seen[v] = true; for (auto e : G[v]) { if (!seen[e.to]) { // 訪問済みでなければ探索 dfs(G, e.to); } } } int main() { int n, m; cin >> n >> m; Graph G(n); for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; G[a].push_back({b}); G[b].push_back({a}); } seen.assign(n, false); // 初期化 int cnt = 0; for (int i = 0; i < n; i++) { if (!seen[i]) { dfs(G, i); cnt++; // dfsした回数をカウント } } cout << cnt << endl; return 0; }
ディスカッション
コメント一覧
まだ、コメントがありません