寻找无向图的双连通分量(Biconnected Components)
字数 1533 2025-11-03 08:34:53
寻找无向图的双连通分量(Biconnected Components)
题目描述
在一个无向连通图中,如果删除任意一个顶点后图仍然保持连通,则该图是双连通的。双连通分量是图的极大双连通子图。寻找双连通分量有助于识别图中的"脆弱点"(即割点),这些点一旦失效会导致图断开。例如,在网络设计中,双连通分量对应冗余路径丰富的区域。题目要求:给定一个无向图,找出其所有双连通分量。
解题过程
1. 核心概念理解
- 割点(Articulation Point):删除该顶点后,图的连通分量数量增加。
- 桥(Bridge):删除该边后,图的连通分量数量增加。
- 双连通分量:不含割点的极大连通子图,分量内任意两点至少存在两条不相交路径。
- 关键性质:双连通分量通过割点连接,且每条边恰好属于一个双连通分量。
2. 算法选择:基于DFS的Tarjan算法变体
使用深度优先搜索(DFS)遍历图,同时维护两个关键值:
disc[u]:顶点u的发现时间(DFS首次访问时间)。low[u]:从u出发通过DFS树边和后向边能访问到的最早祖先的disc值。
步骤:
- 从任意顶点开始DFS,记录每个顶点的
disc和low。 - 当发现边
(u, v)时:- 若
v未访问(树边):递归访问v,更新low[u] = min(low[u], low[v])。- 若
low[v] >= disc[u],则u是割点(根节点需特殊判断子节点数)。
- 若
- 若
v已访问且不是父节点(后向边):更新low[u] = min(low[u], disc[v])。
- 若
- 用栈记录边:当检测到割点时,弹出栈中边直到当前边
(u, v),这些边构成一个双连通分量。
3. 详细步骤示例
假设无向图如下(边集:AB, BC, CD, CE, DE, EF):
A — B — C — E — F
\ /
D
- 初始化:
disc和low初始为-1,栈为空。 - DFS从A开始:
- 访问A(disc=0, low=0),邻接B(未访问),压栈边AB,递归B。
- 访问B(disc=1, low=1),邻接C(未访问),压栈BC,递归C。
- 访问C(disc=2, low=2),邻接D(未访问),压栈CD,递归D。
- 访问D(disc=3, low=3),邻接C(已访问,但C是父节点,忽略),邻接E(未访问),压栈DE,递归E。
- 访问E(disc=4, low=4),邻接C(已访问且非父节点,后向边):更新
low[E] = min(4, disc[C]=2) = 2。邻接F(未访问),压栈EF,递归F。 - F无未访问邻居,回溯到E。边EF弹出作为分量{EF}。
- E回溯到D:更新
low[D] = min(3, low[E]=2) = 2。 - D回溯到C:更新
low[C] = min(2, low[D]=2) = 2。 - C邻接E(已访问且非父节点):更新
low[C] = min(2, disc[E]=4) = 2。
- 检测割点:
- 回溯时,C的子节点D的
low[D]=2 >= disc[C]=2,故C是割点。弹出栈中边直到CD,得到分量{CD, DE, CE}。 - 继续回溯,B的子节点C的
low[C]=2 >= disc[B]=1,故B是割点。弹出边BC,得分量{BC}。 - 最后栈中剩余AB,弹出得分量{AB}。
- 回溯时,C的子节点D的
4. 结果
双连通分量:{AB}, {BC}, {CD, DE, CE}, {EF}。割点为B和C。
关键点总结
- 利用
low值判断割点:若子节点无法绕过当前顶点访问更早祖先,则该顶点是割点。 - 栈管理边:确保每条边仅属于一个分量。
- 时间复杂度:O(V+E),与DFS相同。