强连通分量
外观
强连通分量简介[编辑 | 编辑源代码]
强连通分量(Strongly Connected Component, SCC)是有向图中的一个极大子图,其中任意两个顶点互相可达(即存在双向路径)。形式化定义为:对于有向图 ,其强连通分量是顶点集 ,满足:
- 对任意 ,存在 和 的路径。
- 不存在更大的集合 满足上述条件。
关键性质[编辑 | 编辑源代码]
- 有向图的强连通分量构成其顶点的划分(即不重叠且覆盖全图)。
- 将每个 SCC 缩为一个顶点后,得到的是有向无环图(DAG)。
算法实现[编辑 | 编辑源代码]
常用算法包括 Kosaraju 算法和 Tarjan 算法。以下以 Kosaraju 算法为例:
Kosaraju 算法步骤[编辑 | 编辑源代码]
1. 第一次 DFS:对原图 进行深度优先搜索,按完成时间逆序记录顶点。 2. 反转图:构造 的转置图 (所有边反向)。 3. 第二次 DFS:按逆序在 上 DFS,每棵树对应一个 SCC。
代码示例[编辑 | 编辑源代码]
from collections import defaultdict
def kosaraju(graph):
visited = set()
order = []
# 第一次DFS生成逆序
def dfs(u):
stack = [(u, False)]
while stack:
node, processed = stack.pop()
if processed:
order.append(node)
continue
if node in visited:
continue
visited.add(node)
stack.append((node, True))
for v in graph[node]:
if v not in visited:
stack.append((v, False))
for u in graph:
if u not in visited:
dfs(u)
# 构造转置图
transposed = defaultdict(list)
for u in graph:
for v in graph[u]:
transposed[v].append(u)
# 第二次DFS找SCC
visited.clear()
sccs = []
for u in reversed(order):
if u not in visited:
stack = [u]
visited.add(u)
component = []
while stack:
node = stack.pop()
component.append(node)
for v in transposed[node]:
if v not in visited:
visited.add(v)
stack.append(v)
sccs.append(component)
return sccs
# 示例输入
graph = {
0: [1],
1: [2],
2: [0, 3],
3: [4],
4: [5],
5: [3]
}
print(kosaraju(graph)) # 输出: [[0, 2, 1], [3, 5, 4]]
输入输出说明[编辑 | 编辑源代码]
- 输入:有向图的邻接表表示。
- 输出:强连通分量列表,每个分量是顶点的集合。示例中 SCC 为 和 。
可视化示例[编辑 | 编辑源代码]
- SCC 1: 0 ↔ 1 ↔ 2
- SCC 2: 3 ↔ 4 ↔ 5
实际应用[编辑 | 编辑源代码]
1. 编译器优化:检测代码中的循环依赖(如函数调用图)。 2. 社交网络分析:识别紧密互动的用户群体。 3. 电路设计:分析信号传播路径的强连通性。
复杂度分析[编辑 | 编辑源代码]
- 时间复杂度:(两次 DFS)。
- 空间复杂度:(存储逆序和转置图)。
扩展阅读[编辑 | 编辑源代码]
- Tarjan 算法:通过单次 DFS 和栈维护实现,效率更高。
- Gabow 算法:类似 Tarjan,但使用不同栈管理方式。