Tarjan–强连通分量
在有向图G中,如果两个顶点u,v间有一条从u到v的有向路径,又有一条从v到u的有向路径
则称两个顶点强连通
如果有向图G的每两个顶点都强连通,称G是一个强连通图
有向图的极大强连通子图,称为强连通分量
void tarjan(int u)
{
low[u]=dfn[u]=++cnt;
st[++top]=u; ins[u]=1;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]);}
else if(ins[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
++colnum;
do{
col[st[top]]=colnum;
ins[st[top]]=0;
}
while(st[top--]!=u);
}
}
void solve()
{
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
}
Tarjan–割点(割顶)
void tarjan(int u)
{
int flag=0;
low[u]=dfn[u]=++cnt;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
flag++;
if(u!=rt||flag>1)cut[u]=1;
}
}
else low[u]=min(low[u],dfn[v]);
}
}
void solve()
{
for(int i=1;i<=n;i++)
if(!dfn[i]) rt=i,tarjan(i);
}
Tarjan–点双连通分量(v-DCC)
void tarjan(int u)
{
dfn[u]=low[u]=++num;
st[++top]=u;
if(u==rt&&head[u]==0){ dcc[++cnt].push_back(u); return;}
int flag=0;
for(int i=head[u];i;i=E[i].nxt)
{
int v=E[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
flag++;
if(u!=rt||flag>1) cut[u]=1;
cnt++; int tt;
do{
tt=st[top--];
dcc[cnt].push_back(tt);
}while(tt!=v);
}
dcc.push_back(u);
}
else low[u]=min(low[u],dfn[v]);
}
}
for(int i=1;i<=n;++i)
if(!dfn[i]) rt=i,tarjan(i);