首先是求强连通分量:
这个的思路大致就是每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。
定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。
代码如下(伪):

1 void tarjan(int x)
2 {
3 dfn[x]=low[x]=++cnt;
4 instack[x]=1;
5 s.push(x);
6 int y;
7 for(int i=head[x];i;i=e[i].nxt)
8 {
9 y=e[i].to;
10 if(!dfn[y])
11 {
12 tarjan(y);
13 low[x]=min(low[x],low[y]);
14 }
15 else if(instack[y]) low[x]=min(low[x],dfn[y]);
16 }
17 y=0;
18 if(dfn[x]==low[x])
19 {
20 tot++;
21 while(x!=y)
22 {
23 y=s.top();
24 s.pop();
25 instack[y]=0;
26 belong[y]=tot;
27 }
28 }
29 }
30 void solve()
31 {
32 tot=cnt=0;
33 memset(dfn,0,sizeof(dfn));
34 For(i,1,n)
35 if(!dfn[i]) tarjan(i);
36 }
