模板题目:http://poj.org/problem?id=2553
Kosaraju:按顺序对原图和反图DFS一遍,在第二次DFS时点u可达未DFS的点v则u,v属于同一个联通分量
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<map> #include<vector> #include<set> #include<cmath> #include<cstdlib> #include<algorithm> #include<stack> using namespace std; const int maxn = 5005; int out[maxn]; int in[maxn]; vector<int> G[maxn]; vector<int> Gr[maxn]; vector<int> rG[maxn]; vector<int> P[maxn]; vector<int> ps; int ID[maxn]; int n, m; bool vis[maxn]; void DFS(int u) { vis[u] = true; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(!vis[v]) DFS(v); } ps.push_back(u); } void RDFS(int u, int x) { vis[u] = true; ID[u] = x; P[x].push_back(u); for(int i = 0; i < Gr[u].size(); i++) { int v = Gr[u][i]; if(!vis[v]) RDFS(v, x); } } void init() { memset(out, 0, sizeof(out)); ps.clear(); for(int i = 1; i <= n; i++) { G[i].clear(); Gr[i].clear(); rG[i].clear(); P[i].clear(); } } int Kosaraju() { int res = 0; memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) { if(!vis[i]) DFS(i); } memset(vis, 0, sizeof(vis)); for(int i = ps.size() - 1; i + 1; i--) { int v = ps[i]; if(!vis[v]) RDFS(v, ++res); } return res; } void Get_DAG() { for(int u = 1; u <= n; u++) { for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(ID[u] != ID[v]) { rG[ID[u]].push_back(ID[v]); out[ID[u]]++; } } } } int main() { while(cin >> n, n) { cin >> m; init(); for(int i = 0; i < m; i++) { int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); Gr[v].push_back(u); } Kosaraju(); Get_DAG(); vector<int> ans; for(int i = 1; i <= n; i++) { if(!out[i] && P[i].size()) { for(int j = 0; j < P[i].size(); j++) { int v = P[i][j]; ans.push_back(v); } } } sort(ans.begin(), ans.end()); for(int i = 0; i < ans.size(); i++) { int v = ans[i]; cout << v << (v == ans.back() ? '\n' : ' '); } } return 0; }
Tarjan:
#include<cstdio> #include<iostream> #include<cstring> #include<queue> #include<map> #include<vector> #include<set> #include<cmath> #include<cstdlib> #include<algorithm> #include<stack> using namespace std; const int maxn = 5005; int out[maxn]; stack<int> S; vector<int> G[maxn]; vector<int> rG[maxn]; vector<int> P[maxn]; bool isinstack[maxn]; int low[maxn], dfn[maxn]; int ID[maxn]; int n, m, ssc_num, index; void Get_DAG() { for(int u = 1; u <= n; u++) { for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(ID[u] != ID[v]) { rG[ID[u]].push_back(ID[v]); out[ID[u]]++; } } } } void init() { memset(out, 0, sizeof(out)); memset(ID, -1, sizeof(ID)); memset(low, -1, sizeof(low)); memset(dfn, -1, sizeof(dfn)); memset(isinstack, 0, sizeof(isinstack)); while(!S.empty()) S.pop(); index = 1; for(int i = 1; i <= n; i++) P[i].clear(), G[i].clear(), rG[i].clear(); } void TarDFS(int u) { dfn[u] = index++; low[u] = dfn[u]; isinstack[u] = 1; S.push(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(dfn[v] == -1) { TarDFS(v); low[u] = min(low[u], low[v]); } else { if(isinstack[v] && low[u] > dfn[v]) { low[u] = dfn[v]; } } } if(dfn[u] ==low[u]) { ssc_num++; while(S.top() != u) { isinstack[S.top()] = 0; ID[S.top()] = ssc_num; P[ssc_num].push_back(S.top()); S.pop(); } isinstack[u] = 0; ID[u] = ssc_num; P[ssc_num].push_back(u); S.pop(); } } int Tarjan() { ssc_num = 0; index = 1; for(int i = 1; i <= n; i++) { if(dfn[i] == -1) { TarDFS(i); } } return ssc_num; } int main() { while(cin >> n, n) { cin >> m; init(); for(int i = 0; i < m; i++) { int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); } Tarjan(); Get_DAG(); vector<int> ans; for(int i = 1; i <= n; i++) { if(!out[i] && P[i].size()) { for(int j = 0; j < P[i].size(); j++) { int v = P[i][j]; ans.push_back(v); } } } sort(ans.begin(), ans.end()); for(int i = 0; i < ans.size(); i++) { int v = ans[i]; cout << v << (v == ans.back() ? '\n' : ' '); } } return 0; }
转载请标明出处:分解强连通分量
文章来源: 分解强连通分量