- 割点:删除该点后,图的连通分量数增加
- 割边(桥):删除该边后,图的连通分量数增加
- 点双连通分量:无向图中极大的不含割点的连通子图
- 边双连通分量:无向图中极大的不含割边的连通子图
算法思路:
割点:
- 根节点:如果有多于1个子树,则为割点
- 非根节点u:存在子节点v,使得low[v]>=dfn[u]
割边:
- 对于边(u,v),若low[v]>dfn[u],则该边为割边
点双连通分量:
- 使用栈存储边
- 当发现low[v]>=dfn[u]时,从栈中弹出边直到当前边,这些边属于同一个点双
边双连通分量:
- 先求出所有割边
- 删除所有割边后,剩余的连通块就是边双连通分量
P3388 割点
// dfn[u]: 节点u的DFS序号(时间戳) |
P8435 点双连通分量
|
P8436 边双连通分量
|
代码说明:
- 点双连通分量:
- 使用栈存储节点
- 当发现割点条件时,从栈中弹出节点直到当前子节点
- 注意根节点需要特殊处理
- 边双连通分量:
- 先求出所有桥
- 删除桥后,剩下的连通块就是边双连通分量
- 使用DFS标记每个节点所属的边双连通分量
- 注意处理重边和自环的情况
缩点(找环)
- Tarjan-SCC:dfn/low+栈,dfn[u]==low[u] 时弹栈成一个强连通分量。
- 缩点建图:对每条原边(u,v),若scc[u]!=scc[v],连边 scc[u]→scc[v],并统计入度。
|
强连通分量
在有向图G中,如果两个顶点u,v间有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个顶点强连通。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向非强连通图的极大强连通子图,称为强连通分量。
Tarjan-SCC:DFS维护 dfn/low 和一个栈,节点入栈并标记在栈中。
遍历边(u→v):
若 v 未访问,递归后 low[u]=min(low[u],low[v]);
若 v 在栈内,low[u]=min(low[u],dfn[v])。
若 dfn[u]==low[u],从栈中弹出直到 u,得到一个SCC。
输出:把每个点按所属SCC收集并排序;按点编号1…n扫描,遇到“第一次出现”的SCC就输出一行。
const int N=10005; |