强连通分量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 */

 

posted @ 2013-08-10 11:50  crazy_apple  阅读(190)  评论(0编辑  收藏  举报