图的点双连通分量
连通分量中无割点,即除去一个点及其边,图仍然连通
void tarjan(int u,int fa0){//点双
dfn[u] = low[u] = ++ cnt;
for (int i = 0;i < G[u].size();i ++){
int v = G[u][i];
if (!dfn[v]){
s[++ siz] = v;
tarjan(v,u);
if (low[v] >= dfn[u]){
num ++;
while (1){
int t1;
t1 = s[siz];
fa[t1].push_back(num);
tot[num] ++;
siz --;
if (t1 == u)
break;
}
}
low[u] = min(low[u],low[v]);
}
else if (v != fa0 && dfn[v] < dfn[u]){
s[++ siz] = v;
low[u] = min(low[u],dfn[v]);
}
}
}
图的边双连通分量
图的连通分量中无割边,即去除一条边,图仍然连通
void tarjan(int u,int fa0){
dfn[u] = low[u] = ++cnt;
s[++ siz] = u;
for (int i = 0;i < G[u].size();i ++){
int v = G[u][i];
if (!dfn[v]){
tarjan(v,u);
low[u] = min(low[u],low[v]);
}
else if (v != fa0)
low[u] = min(low[u],dfn[v]);
}
if (low[u] == dfn[u]){
num ++;
fa[u] = num;
while (s[siz] != u){
fa[s[siz]] = num;
siz --;
}
siz --;
}
}
强连通分量
有向图的连通分量中每两个点都可以互相到达
void tarjan(int u){
dfn[u] = low[u] = ++ cnt;
s[++ siz] = u;
instuck[u] = 1;
for (int i = 0;i < G[u].size();i ++){
int v = G[u][i];
if (!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
}
if (instuck[v])
low[u] = min(low[u],low[v]);
}
if (low[u] == dfn[u]){
num ++;
instuck[u] = 0;
while (s[siz] != u){
instuck[s[siz]] = 0;
siz --;
}
siz --;
}
}