Tarjan
在dfs的过程中记录时间戳与每个点可到达的时间戳最小的点
记:low当前可已过的时间戳最小的,dfn当前点的时间戳
缩点
顾名思义,缩点就是把一个强连通分量缩成一个点
inline void Tarjan(int x)// st栈,co当前点属于的强连通分量
{
low[x]=dfn[x]=++cnt;
st[++top]=x,vis[x]=1;
for(re int i=h[x];i;i=e[i].ne)
{
int y=e[i].to;
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])
{
++color;
while(st[top+1]!=x)
{
co[st[top]]=color;
vis[st[top--]]=0;
}
}
}
割点
设该点为u,分为两种情况:
1.该点为根,且不止一个儿子
2.不为树根,该点的儿子v的low[v]>=dfn[u],(即v与v的子树无法通过任何边到达u以上)
inline void Tarjan(int u)
{
low[u]=dfn[u]=++cnt;
st[++top]=u,vis[u]=1;
int son=0;
for(re int i=h[u];i;i=e[i].ne)
{
int v=e[i].to;
if(!dfn[v])
{
son++;
Tarjan(v);
low[u]=min(low[u],low[v]);
if((u==root && son>1) || (u!=root && dfn[x]<=low[y])) flag[u]=1;
}
else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
}
桥
与求割点相似,low[v]>=dfn[u]时它们中间的边即为桥 (不贴代码了)