aoj GRL_3 Connected Components - Strongly Connected Components
問題概要
強連結成分分解する問題。
解法
強連結成分を分解するアルゴリズムとして、Kosarajuというものがある。今回はそれを使って、実装した。アルゴリズム自体は下のサイトを見てもらえれば、分かりやすい。
ミス
アルゴリズム自体の理解が不十分。なんとなく、2回dfsすれば、いいのはわかるけど。
コード
#include <iostream> #include <vector> #include <cstdio> #include <string> #include <cstring> using namespace std; #define rep(i,n) for(int i=0;i<(n);i++) ///強連結成分分解 (Kosaraju)/// #define MAX_V 10000//頂点数 int V; vector<int> G[MAX_V], rG[MAX_V]; vector<int> vs; bool used[MAX_V]; //cmp[v] = cmp[U]なら、頂点u, vは同じ強連結成分 int cmp[MAX_V];//cmp[v] := 頂点vが含まれる連結成分がどれなのかを示す番号 //隣接リストを作る void add_edge(int from, int to){//0origin G[from].push_back(to);//与えられた有向グラフの隣接リスト rG[to].push_back(from);//与えられたグラフの矢印を逆した有向グラフの隣接リスト } //一度目のdfs void dfs(int v){ used[v] = true; for (int i = 0; i < G[v].size(); ++i){ if(!used[G[v][i]]) dfs(G[v][i]); } vs.push_back(v);//これ以上進めなくなったものから順にvsに頂点番号を入れていく } //2度目のdfs void rdfs(int v, int k){ used[v] = true; cmp[v] = k;//頂点vに対して、k番目と強連結成分であること入れる for (int i = 0; i < rG[v].size(); ++i){ if(!used[rG[v][i]]) rdfs(rG[v][i], k); } } int scc(){ memset(used, 0, sizeof(used));//0(使ってない)で初期化 vs.clear();//初期化 for (int v = 0; v < V; ++v){ if(!used[v]) dfs(v); } memset(used, 0 , sizeof(used)); int k = 0;//強連結成分を分ける番号 for (int i = vs.size() - 1; i >= 0; --i){//vsに入っている後ろのものからdfs if(!used[vs[i]]){ rdfs(vs[i], k); k++; } } return k; } int main(void){ int E, s, t; cin >> V >> E; rep(i, E){ cin >> s >> t; add_edge(s, t);//頂点sとtを辺として繋ぐ s -> t } scc();//強連結成分を作る int q, u, v; cin >> q; rep(i, q){ cin >> u >> v; if(cmp[u] == cmp[v]) printf("1\n"); else printf("0\n"); } return 0; }