有向グラフ g の部分頂点集合 S が強連結であるとは,任意の x, y \in S に対して有向道 x --> y が存在することをいう.同じ強連結成分に入ることは同値関係となるので,この同値関係でグラフを分解することができる.これを強連結成分分解という.
強連結成分分解を求めるために,しばしば二回の深さ優先探索を行うアルゴリズムが紹介されるが,そのアルゴリズムでは逆グラフを作る必要がある.以下のアルゴリズムは,逆グラフを作らず,一回の深さ優先探索でそれを行う.
O(V+E)
void visit(const Graph &g, int v, vector< vector<int> >& scc, stack<int> &S, vector<bool> &inS, vector<int> &low, vector<int> &num, int& time) { low[v] = num[v] = ++time; S.push(v); inS[v] = true; FOR(e, g[v]) { int w = e->dst; if (num[w] == 0) { visit(g, w, scc, S, inS, low, num, time); low[v] = min(low[v], low[w]); } else if (inS[w]) low[v] = min(low[v], num[w]); } if (low[v] == num[v]) { scc.push_back(vector<int>()); while (1) { int w = S.top(); S.pop(); inS[w] = false; scc.back().push_back(w); if (v == w) break; } } } void stronglyConnectedComponents(const Graph& g, vector< vector<int> >& scc) { const int n = g.size(); vector<int> num(n), low(n); stack<int> S; vector<bool> inS(n); int time = 0; REP(u, n) if (num[u] == 0) visit(g, u, scc, S, inS, low, num, time); }
Last Modified: 2007.05.28 15:50:06.