强连通分量 (SCC) 模板详解
1. 简介
强连通分量(Strongly Connected Component,
SCC)是有向图中的一个极大子图,其中任意两点之间都存在相互可达的路径。本模板使用
Tarjan 算法实现了强连通分量的计算。
主要特点:
- 支持有向图的强连通分量分解
- 基于 Tarjan 算法实现
- 时间复杂度 O(V + E)
- 可用于缩点构建DAG
2. 实现原理
2.1 基本概念
强连通分量:
Tarjan算法:
- 基于DFS的单次遍历算法
- 使用时间戳和追溯值识别强连通分量
2.2 核心策略
DFS遍历:
- 维护时间戳(dfn)记录访问顺序
- 维护追溯值(low)记录可追溯的最早时间戳
栈维护:
- 使用栈记录访问路径
- 当dfn[x] = low[x]时找到一个强连通分量
3. 模板代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| struct SCC { int n; std::vector<std::vector<int>> adj; std::vector<int> stk; std::vector<int> dfn, low, bel; int cur, cnt; SCC() {} SCC(int n) { init(n); } void init(int n) { this->n = n; adj.assign(n, {}); dfn.assign(n, -1); low.resize(n); bel.assign(n, -1); stk.clear(); cur = cnt = 0; } void addEdge(int u, int v) { adj[u].emplace_back(v); } void dfs(int x) { dfn[x] = low[x] = cur++; stk.emplace_back(x); for (auto y : adj[x]) { if (dfn[y] == -1) { dfs(y); low[x] = std::min(low[x], low[y]); } else if (bel[y] == -1) { low[x] = std::min(low[x], dfn[y]); } } if (dfn[x] == low[x]) { int y; do { y = stk.back(); bel[y] = cnt; stk.pop_back(); } while (y != x); cnt++; } } std::vector<int> work() { for (int i = 0; i < n; i++) { if (dfn[i] == -1) { dfs(i); } } return bel; } };
|
4. 函数说明
4.1 构造和初始化
1 2 3
| SCC() SCC(int n) void init(int n)
|
- 支持默认构造和指定大小构造
- 初始化所有必要的数组和变量
4.2 核心操作
1 2
| void addEdge(int u, int v) std::vector<int> work()
|
addEdge
: 添加有向边
work
: 计算强连通分量并返回每个点所属的分量编号
5. 时间复杂度分析
初始化:O(V)
核心操作:O(V + E)
空间复杂度:O(V + E)
6. 应用场景
- 有向图的环检测
- 2-SAT问题求解
- 游戏关卡依赖分析
- 社交网络社群发现
- 编译依赖分析
7. 使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int n = 5; SCC scc(n);
scc.addEdge(0, 1); scc.addEdge(1, 2); scc.addEdge(2, 0); scc.addEdge(2, 3); scc.addEdge(3, 4);
auto bel = scc.work();
for (int i = 0; i < n; i++) { std::cout << "Node " << i << " belongs to component " << bel[i] << "\n"; }
|
8. 注意事项
- 输入必须是有向图
- 节点编号从0开始
- 强连通分量编号不保证按拓扑序
- 多个连通分量的情况会自动处理
9. 总结
强连通分量是有向图分析中的重要工具,本模板通过 Tarjan
算法高效实现了SCC的计算。它可以用于解决各种图论问题,特别是在需要处理有向图的环结构时非常有用。