【step1】画出搜索树。
【step2】在树上补上指向染色过点的边(打上叉,记作打叉边)
【setp3】看搜索树理解四种边的概念,并记住low计算公式
1)树枝边——搜索树上的所有边, 对于边(u,v),有low[u]=min{low[u],low[v]}。
2)前向边——打叉边中起点u指向某个祖先节点v的边,不用计算low值。
3)后向边——打叉边中起点u指向某个子孙v的边,有low[u]=min{low[u],dfn[v]}。
4)横叉边——打叉边中起点u指向另一分枝v的边,有low[u]=min{low[u],dfn[v]},强调说明:4)中的v即不是u的子孙,也不是u的祖先。
void Tarjan(int u){//Tarjan求SCC
dfn[u]=low[u]=++num;//num表示时间戳的序号
stack[++top]=u;
for(int i=head[u];i;i=next[i]){
int v=to[i];
if(!dfn[v]){//点v还不有入栈
Tarjan(v);
low[u]=min(low[u],low[v]);//(u,v)树枝边
}
else if(!co[v])//(u,v)后向边或横叉边,且点v没有出栈
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
co[u]=++col;//染色,SCC内的点都标为col
++si[col];//统计当前SCC中的结点数
while(st[top]!=u){
co[st[top]]=col;
++si[col];
--top;
}
--top;//满足stack[top]=u的SCC的根u,出栈
}
}