核心概述

强连通分量(Strongly Connected Components, SCC):将有向图分解为若干子图,使每个子图内任意两点互相可达;将每个分量收缩为点可得到无环的凝聚图(DAG)。典型算法为 Kosaraju(两遍 DFS)或 Tarjan(单遍栈法),复杂度 O(N+M)。

原文引述

Description: Decompose a directed graph into strongly connected components; build the condensation DAG. Implemented via Kosaraju or Tarjan. Time: O(N + M) Status: tested

展开阐述

  • 函数/接口(据实现)

    • scc(G) → {C, comp}:
      • C:分量个数。
      • comp[v] ∈ [0, C) 为顶点 v 所在分量编号(常可保证按拓扑序编号,便于后续 DP)。
    • 可选:根据 comp 构建凝聚图 DAG(对每条边 u→v,若 comp[u]≠comp[v],连 comp[u]→comp[v] 并去重)。
  • 算法A:Kosaraju(两遍 DFS)

    1. 在原图上做 DFS,按“退出时间”将顶点压入序列 order。
    2. 在反图上,按 order 的逆序依次作为起点再做 DFS,访问到的点构成一个强连通分量并赋同一编号。
    • 需要构建反图,思路直观,实现简洁。
  • 算法B:Tarjan(单遍 + 栈)

    • 维护 dfn[u](时间戳)、low[u]、栈 stk 与 inStack 标记。
    • DFS(u) 时:
      • dfn[u]=low[u]=timer++,u 入栈。
      • 遍历 u→v:
        • 若 v 未访问:DFS(v),low[u]=min(low[u], low[v])。
        • 否则若 v 在栈:low[u]=min(low[u], dfn[v])。
      • 若 low[u]==dfn[u]:从栈中弹出直到 u,形成一个分量并编号。
    • 单遍完成,无需反图,常数因子小。
  • 输出语义

    • C:强连通分量数。
    • comp[v]:顶点 v 的分量编号。
    • 凝聚图为 DAG,可在其上进行拓扑排序与 DP。
  • 复杂度

    • 两种算法均为 O(N+M);内存开销与图存储一致。
  • 使用与注意

    • 若需检测是否存在环:判断 C 是否小于 N 或检查 comp[u]==comp[v] 的回边。
    • 在 2-SAT 中,若某变量 x 与 ¬x 落在同一分量则无解(见 051-图论-2SAT)。
    • 在凝聚图上可配合 078-图论-拓扑排序 做分量级别的 DP。

关联节点