强连通分量(有向图)
void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
stac[++top]=x;
vis[x]=1;
for(int i=hd[x];i;i=nxt[i])
{
int y=go[i];
if(!dfn[y])//树边
{tarjan(y);low[x]=min(low[x],low[y]);}
else if(vis[y])low[x]=min(low[x],dfn[y]);//在栈中(判横叉边)
}
if(low[x]==dfn[x])//出不去
{
col_cnt++;
while(stac[top+1]!=x){
c[stac[top]]=col_cnt;
vis[stac[top]]=0;
ve[col_cnt].push_back(stac[top]);
top--;
}
}
}
边双连通分量(无向图)
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++cnt;
stac[++top]=u;
int son=0;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!dfn[v])
{
son++;
tarjan(v,i);
low[u]=min(low[v],low[u]);
}
else if(i!=(fa^1)) low[u]=min(low[u],dfn[v]);//可以通过重边走向父亲
}
if(low[u]==dfn[u])
{
++col;
while(stac[top+1]!=u)
{
ans[col].push_back(stac[top--]);
}
}
return ;
}
点双连通分量(无向图)
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++cnt;
stac[++top]=u;
int son=0;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(!dfn[v])
{
son++;
tarjan(v,u);
low[u]=min(low[v],low[u]);
if(low[v]>=dfn[u])
{
++col;
while(stac[top+1]!=v)
{
ans[col].push_back(stac[top--]);
}
ans[col].push_back(u);//因为一个割点可能属于多个点双,所以不能出栈
}
}
else if(v!=fa) low[u]=min(low[u],dfn[v]);
}
if(fa==0&&son==0)ans[++col].push_back(u);//特判独立点
return ;
}
标签:tarjan,int,top,++,dfn,low,模板,stac
From: https://www.cnblogs.com/storms11/p/18572072