TOP > グラフ 強連結成分分解 強連結成分分解(Strongly-Connected-Components) 2018/03/31 • ei1333 説明 強連結成分分解をする。 計算量 $O(V + E)$ 実装例 StronglyConnectedComponents($g$):= グラフ $g$ で初期化する。 build($t$):= 強連結成分分解をする。強連結成分の番号はトポロジカル順に昇順にふられる。 $t$ には強連結成分ごとに縮約したグラフが格納される(多重辺が生えるので注意)。 [$k$] := 頂点 $k$ が属する強連結成分の番号を返す。 template< typename G > struct StronglyConnectedComponents { const G &g; UnWeightedGraph gg, rg; vector< int > comp, order, used; StronglyConnectedComponents(G &g) : g(g), gg(g.size()), rg(g.size()), comp(g.size(), -1), used(g.size()) { for(int i = 0; i < g.size(); i++) { for(auto e : g[i]) { gg[i].emplace_back((int) e); rg[(int) e].emplace_back(i); } } } int operator[](int k) { return comp[k]; } void dfs(int idx) { if(used[idx]) return; used[idx] = true; for(int to : gg[idx]) dfs(to); order.push_back(idx); } void rdfs(int idx, int cnt) { if(comp[idx] != -1) return; comp[idx] = cnt; for(int to : rg[idx]) rdfs(to, cnt); } void build(UnWeightedGraph &t) { for(int i = 0; i < gg.size(); i++) dfs(i); reverse(begin(order), end(order)); int ptr = 0; for(int i : order) if(comp[i] == -1) rdfs(i, ptr), ptr++; t.resize(ptr); for(int i = 0; i < g.size(); i++) { for(auto &to : g[i]) { int x = comp[i], y = comp[to]; if(x == y) continue; t[x].push_back(y); } } } }; 検証 AOJ GRL_3_C 強連結成分分解 #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_3_C" #include "../../template/template.cpp" #include "../template.cpp" #include "../strongly-connected-components.cpp" int main() { int V, E, Q; scanf("%d %d", &V, &E); UnWeightedGraph g(V), buff; for(int i = 0; i < E; i++) { int a, b; scanf("%d %d", &a, &b); g[a].emplace_back(b); } StronglyConnectedComponents< UnWeightedGraph > scc(g); scc.build(buff); scanf("%d", &Q); while(Q--) { int a, b; scanf("%d %d", &a, &b); puts(scc[a] == scc[b] ? "1" : "0"); } }