tarjan复健
2-SAT
区分 tarjan 解决三个连通性的东西时的变化。
强连通分量
只针对有向图的概念,即任意两点连通的极大子图。
在 tarjan 中要比无向图多考虑一个横叉边,即 dfs 时遇到一个原来访问过的边但不能形成强连通分量。
如蓝边为横叉边。
定义 low 为从 u 出发能到达的 dfn 序最小的点,但每次求完 SCC 相当于把该点删去来定义 low。
所以,我们维护一个队列表示可能能成为 SCC 的点,记录一个 ins 表示是否在访问队列里,如果更新的点被访问过且在队列中,就更新他的 low,否则证明该点已经成为强连通分量了,相当于把这个点删去了,不用更新。
更新 low 的时候因为定义可以写成 low[p]=min(low[p],low[i])。
void tarjan(int p)
{
dfn[p]=low[p]=++ndf; q.pb(p); ins[p]=1;
G(i,p)
{
if(!dfn[i])
{
tarjan(i);
low[p]=min(low[p],low[i]);
}
else if(ins[i])
{
low[p]=min(low[i],low[p]);
}
}
if(dfn[p]==low[p])//now is the lead of SCC from q.back()->p
return ;
}
点双连通分量
无向图中只有返祖边,没有回边。low 的定义变为回溯后到达的最小的点编号。
先找割点,找到后如果
因为一个点可能被多个点双包含,所以不能把当前点出队,同时也要在遍历儿子的时候记录点双。
边双连通分量
显然每条边仅属于一个边双中。
先求出割边,然后把这条边标记为不能走,然后 dfs 即可。tarjan 找割边,low 的定义与点双相同,注意判断是否割边的时候与点双不同,如果