图论——割点与割边

admin 2025-09-27 13:02:31 2022世界杯直播

图论——割点与割边

图论——割点与割边

GJX_Algorithm

·

2024-11-02 10:57:19

·

算法·理论

割点与割边

割点

前置知识

建议先学强连通分量,学会 dfn 数组与 low 数组后再来学习割点。

点双连通:在无向图中,删除一个点(不是 x 或者 y)后,点 x 和点 y 仍然能够彼此到达,那么称 x 和 y 是点双连通的。

边双连通:在无向图中,删除一条边后,点 x 和点 y 仍然能够彼此到达,那么称 x 和 y 是边双连通的。

点双连通不具有传递性(如图),边双连通具有传递性。

割点的定义,结论,与判定

定义:在无向图 G 中,若删除 cur 后,连通块的数量增加,则 cur 称为无向图 G 的一个割点(割顶)。

结论:至少有 3 个点的无向图,才可能存在割点。

判定:

若搜索树中,有从 cur 到 nxt 的连边,当 low_{nxt} \ge dfn_{cur} 时,说明 nxt 能到达的最小时间戳在 cur 的时间戳之上,nxt 被 cur 与 cur 之前的结点“隔开”,cur 可能是割点。

对于所有可能的割点,只要 cur 不是搜索树的根结点,或者 cur 是根结点,但是 cur 的子结点大于 1 个,那么 cur 就是割点。

核心代码

void tarjan(int cur)

{

int cnt = 0; //用来统计cur有几个子结点

low[cur] = dfn[cur] = ++tot; //打上时间戳

for (int nxt : nbr[cur])

{

if (dfn[nxt] == 0) //nxt还没去过

{

tarjan(nxt); //递归继续搜索

low[cur] = min(low[cur], low[nxt]); //维护cur能到达的最小时间戳low[cur]

if (low[nxt] >= dfn[cur])

{

cnt++; //nxt还没去过,说明nxt是cur在当前搜索树中的一个子结点

if (cur != root || cnt >= 2) //排除根结点且只有一个子结点的情况

ans[cur] = 1;

}

}

else low[cur] = min(low[cur], dfn[nxt]); //nxt已经去过了,所以nxt还没有回溯,不能用low[nxt]

}

return ;

}

例题与练习

P3388(模板)

UVA10199(模板)

CF1761E

割边

割边的定义、性质与判定

割边的定义:在无向图中,若删除一条边 e 后,连通块的数量增加,那么称边 e 为这张无向图的一条割边。

割边的性质:

割边一定不在环上,在环上的一定不是割边。

割边涉及的通常是“必经边”问题。

若删除一条割边,则联通块数量加一。

割边的判定:

同样先维护出 dfn 值与 low 值。

如图,若 low_{nxt} > dfn_{cur},则边 cur \to nxt 为割边。

核心代码

void edge_add(int u, int v)

{

a[++cnt1] = {u, v};

return ;

}

void tarjan(int u, int fa)

{

dfn[u] = low[u] = ++tot;

for (int i = head[u]; ~i; i = nxt[i])

{

int v = to[i];

if (dfn[v] == 0)

{

tarjan(v, u);

low[u] = min(low[u], low[v]);

if (low[v] > dfn[u]) edge_add(u, v);

}

else if (v != fa) low[u] = min(low[u], dfn[v]);

}

return ;

}

例题与练习

T103481

P1656

P7687