tarjan强连通分量

发布时间 2023-09-10 16:44:31作者: 非常蛋黄yl
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--;
	}