int scc[N],sc;//结点i所在scc的编号
int sz[N]; //强连通i的大小
//dfn(u)为搜到结点u时的次序编号
//low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号
//当dfn(u)=low(u)时,以u为根的搜索子树上的所有节点是一个强连通分量
void tarjan(int u )
{
dfn[u] = low[u]=++dfncnt;//为结点u设定次序编号和low初值
in_stack[u] = true;
s[++tp]=u;//将结点u压入栈中
for(int i = h[u];i;i = e[i].nxt)//枚举每一条边
{
int v = e[i].t;//v为u的子节点
if(!dfn[v])//如果结点v未被访问过
{
tarjan(v);//继续向下找
low[u] = min(low[u],low[v]);//更新最早栈中节点序号
}
else if(in_stack(v))//如果结点v还在栈中
low[u] = min(low[u],low[v]);//更新
}
if(dfn[u]==low[u])//如果节点u是强连通分量的根
{
sc++;//强连通分量的数量++
while(s[tp]!=u)//如果栈顶元素不为u ,回溯
{
scc[s[tp]] = sc;
sz[sc]++;
in_stack[s[tp]] = 0;//将元素出栈
tp--;
}
scc[s[tp]] = sc;
sz[sc]++;
in_stack[s[tp]] = 0;
tp--;
}
标签:结点,连通,int,tarjan,tp,++,dfn,low,分量
From: https://www.cnblogs.com/narcissusyl/p/17691449.html