b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: //------------------------------------------------------------- b57cc94f1b 2011-10-08 kinaba: // Strongly Connected Component of a Directed Graph b57cc94f1b 2011-10-08 kinaba: // O(E) b57cc94f1b 2011-10-08 kinaba: // b57cc94f1b 2011-10-08 kinaba: // Verified by b57cc94f1b 2011-10-08 kinaba: // - SRM 499 Div1 LV3 b57cc94f1b 2011-10-08 kinaba: // 109f2a9050 2012-09-08 kinaba: // Using "Spagetthi Source"'s one pass algorithm b57cc94f1b 2011-10-08 kinaba: //------------------------------------------------------------- b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: template<typename T> b57cc94f1b 2011-10-08 kinaba: class IdGen b57cc94f1b 2011-10-08 kinaba: { b57cc94f1b 2011-10-08 kinaba: map<T, int> v2id_; b57cc94f1b 2011-10-08 kinaba: vector<T> id2v_; b57cc94f1b 2011-10-08 kinaba: public: b57cc94f1b 2011-10-08 kinaba: int v2id(const T& v) { b57cc94f1b 2011-10-08 kinaba: if( !v2id_.count(v) ) { v2id_[v] = size(); id2v_.push_back(v); } b57cc94f1b 2011-10-08 kinaba: return v2id_[v]; b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: const T& id2v(int i) const { return id2v_[i]; } b57cc94f1b 2011-10-08 kinaba: int size() const { return id2v_.size(); } b57cc94f1b 2011-10-08 kinaba: }; b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: template<typename Vert> b57cc94f1b 2011-10-08 kinaba: class SCC b57cc94f1b 2011-10-08 kinaba: { b57cc94f1b 2011-10-08 kinaba: IdGen<Vert> idgen; b57cc94f1b 2011-10-08 kinaba: vector< vector<int> > G; b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: public: b57cc94f1b 2011-10-08 kinaba: void addVert( Vert s_ ) b57cc94f1b 2011-10-08 kinaba: { b57cc94f1b 2011-10-08 kinaba: int s = idgen.v2id(s_); b57cc94f1b 2011-10-08 kinaba: if( s >= G.size() ) G.resize(s+1); b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: void addEdge( Vert s_, Vert t_ ) b57cc94f1b 2011-10-08 kinaba: { b57cc94f1b 2011-10-08 kinaba: int s = idgen.v2id(s_), t = idgen.v2id(t_); b57cc94f1b 2011-10-08 kinaba: if( max(s,t) >= G.size() ) G.resize(max(s,t)+1); b57cc94f1b 2011-10-08 kinaba: G[s].push_back(t); b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: void scc() b57cc94f1b 2011-10-08 kinaba: { b57cc94f1b 2011-10-08 kinaba: int N = G.size(); b57cc94f1b 2011-10-08 kinaba: dfs_no.assign(N, 0); b57cc94f1b 2011-10-08 kinaba: dfs_lo.assign(N, 0); b57cc94f1b 2011-10-08 kinaba: pending = stack<int>(); b57cc94f1b 2011-10-08 kinaba: scc_id.assign(N, -1); b57cc94f1b 2011-10-08 kinaba: scc_list.clear(); b57cc94f1b 2011-10-08 kinaba: scc_children.clear(); b57cc94f1b 2011-10-08 kinaba: for(int v=0; v<N; ++v) b57cc94f1b 2011-10-08 kinaba: dfs(v); b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: vector<int> scc_id; // which scc does the vert belong to? b57cc94f1b 2011-10-08 kinaba: vector< vector<int> > scc_list; // list of nodes in the scc b57cc94f1b 2011-10-08 kinaba: vector< vector<int> > scc_children; // forest relationship of sccs b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: private: b57cc94f1b 2011-10-08 kinaba: int no; b57cc94f1b 2011-10-08 kinaba: vector<int> dfs_no; // 1-origin dfs-visit ID b57cc94f1b 2011-10-08 kinaba: vector<int> dfs_lo; // the least ID in the vert's scc b57cc94f1b 2011-10-08 kinaba: stack<int> pending; // current unclassigied verts b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: void dfs(int v) b57cc94f1b 2011-10-08 kinaba: { b57cc94f1b 2011-10-08 kinaba: // visit v if not yet b57cc94f1b 2011-10-08 kinaba: if( dfs_no[v] ) b57cc94f1b 2011-10-08 kinaba: return; b57cc94f1b 2011-10-08 kinaba: dfs_no[v] = dfs_lo[v] = ++no; b57cc94f1b 2011-10-08 kinaba: pending.push(v); b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: // visit children b57cc94f1b 2011-10-08 kinaba: for(int i=0; i<G[v].size(); ++i) { b57cc94f1b 2011-10-08 kinaba: int u = G[v][i]; b57cc94f1b 2011-10-08 kinaba: dfs( u ); b57cc94f1b 2011-10-08 kinaba: if( scc_id[u] == -1 ) b57cc94f1b 2011-10-08 kinaba: dfs_lo[v] = min( dfs_lo[v], dfs_lo[u] ); b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: // when v is the representative of scc b57cc94f1b 2011-10-08 kinaba: if( dfs_no[v] == dfs_lo[v] ) { b57cc94f1b 2011-10-08 kinaba: vector<int> scc; b57cc94f1b 2011-10-08 kinaba: for(;;) { b57cc94f1b 2011-10-08 kinaba: int w = pending.top(); pending.pop(); b57cc94f1b 2011-10-08 kinaba: scc.push_back(w); b57cc94f1b 2011-10-08 kinaba: scc_id[w] = scc_list.size(); b57cc94f1b 2011-10-08 kinaba: if( w == v ) break; b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: scc_list.push_back(scc); b57cc94f1b 2011-10-08 kinaba: b57cc94f1b 2011-10-08 kinaba: set<int> children; b57cc94f1b 2011-10-08 kinaba: for(int j=0; j<scc.size(); ++j) b57cc94f1b 2011-10-08 kinaba: for(int i=0; i<G[scc[j]].size(); ++i) b57cc94f1b 2011-10-08 kinaba: children.insert( scc_id[G[scc[j]][i]] ); b57cc94f1b 2011-10-08 kinaba: children.erase(scc_id[v]); b57cc94f1b 2011-10-08 kinaba: scc_children.push_back( vector<int>(children.begin(), children.end()) ); b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: } b57cc94f1b 2011-10-08 kinaba: };