基于 DFS 深度生成树及栈结构回溯,通过 DFN 与 LOW 二阶判定,实现极速缩点
在有向图 $G = (V, E)$ 中,若两个顶点 $u$ 和 $v$ 之间存在双向路径,则称它们是强连通的。有向图的极大强连通子图称为强连通分量(SCC,Strongly Connected Component)。
int dfn[MAXN], low[MAXN], timer = 0;
bool instack[MAXN];
stack<int> st;
void tarjan(int u) {
dfn[u] = low[u] = ++timer;
st.push(u); instack[u] = true;
for (int v : g[u]) {
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]); // 树枝边回溯更新
} else if (instack[v]) {
low[u] = min(low[u], dfn[v]); // 反向回退边更新
}
}
if (dfn[u] == low[u]) { // 发现 SCC 根节点
while (true) {
int v = st.top(); st.pop();
instack[v] = false;
scc[v] = scc_cnt; // 缩点分配强连通分量ID
if (u == v) break;
}
scc_cnt++;
}
}