强连通分量Tarjan模板
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<stack> 5 #include<vector> 6 #include<algorithm> 7 8 #define N 1000 9 10 using namespace std; 11 12 int pre[N],lowlink[N],sccno[N],dfn_clock,scc_cnt; 13 14 stack<int> stk; 15 16 vector<int> G[N]; 17 18 void DFN(int u) 19 { 20 pre[u] = lowlink[u] = ++dfn_clock; //时间戳 21 stk.push(u); 22 int i; 23 for(i=0;i<G[u].size();i++) 24 { 25 int v = G[u][i]; 26 if(!pre[v]) //没有访问过 27 { 28 DFN(v); 29 lowlink[u] = min(lowlink[u],lowlink[v]); 30 } 31 else if(!sccno[v]) //被访问过,但是不是其他强连通图的组成 32 { 33 lowlink[u] = min(lowlink[u],pre[v]); 34 } 35 } 36 if(lowlink[u]==pre[u]) //发现一个强连通分量 37 { 38 scc_cnt++; //强连通分量的个数计算 39 while(1) 40 { 41 int x = stk.top(); 42 stk.pop(); 43 sccno[x] = scc_cnt; 44 if(x==u) break; 45 } 46 } 47 } 48 49 void find_scc(int n) 50 { 51 dfn_clock = scc_cnt = 0; 52 memset(sccno,0,sizeof(sccno)); 53 memset(pre,0,sizeof(pre)); 54 int i; 55 for(i=1;i<=n;i++) 56 if(!pre[i]) DFN(i); 57 } 58 59 int main() 60 { 61 int n,m; 62 scanf("%d%d",&n,&m); 63 int i; 64 for(i=0;i<m;i++) 65 { 66 int a,b; 67 scanf("%d%d",&a,&b); 68 G[a].push_back(b); //构造图 69 } 70 find_scc(n); //查找强连通图 71 for(i=1;i<=n;i++) 72 printf("%d ",sccno[i]); 73 putchar(10); 74 return 0; 75 } 76 77 /* 78 //测试用图 79 6 8 80 1 3 81 3 5 82 5 6 83 3 4 84 4 6 85 4 1 86 1 2 87 2 4 88 */