分解强连通分量

匿名 (未验证) 提交于 2019-12-03 00:38:01

模板题目: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; }

转载请标明出处:分解强连通分量
文章来源: 分解强连通分量
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!