图的连通性代码模板(python)

图的连通性代码模板

  • 关于 e − D C C e-DCC eDCC v − D C C v-DCC vDCC 缩点的应用可能结合倍增 L C A LCA LCA 算法,多次回答无向图上两点之间的必经边、必经点的询问。

T a r j a n Tarjan Tarjan算法与无向图连通性

时间戳

在图的深度优先遍历中,按照每个结点第一次被访问的顺序,依次给予 N N N 个结点 1 1 1~ N N N 的整数标记,该标记就被称为“时间戳”,记为 d f n [ x ] dfn[x] dfn[x]

搜索树

在无向连通图中任选一个结点进行 d f s dfs dfs ,每个结点只访问一次。所有发生递归的边 ( x , y ) (x,y) (x,y) 构成一棵树,我们把它称为“无向连通图的搜索树”。一般的无向连通图的各个连通块的搜索树构成无向图的搜索森林。

追溯值

返祖边:搜索树上的一个点连向其祖先结点的边

横插边:搜索树上一个点连向它另一条支链上的点的边(只存在于有向图)

l o w [ x ] low[x] low[x] 定义为当前点及其子树的仅通过一条返祖边能连到 d f n dfn dfn 值最小的点

( u , v ) (u,v) (u,v) 是树边: l o w [ u ] = m i n ( l o w [ u ] , l o w [ v ] ) low[u] = min(low[u],low[v]) low[u]=min(low[u],low[v])

( u , v ) (u,v) (u,v) 是返祖边: l o w [ u ] = m i n ( l o w [ u ] , d f n [ v ] ) low[u] = min(low[u],dfn[v]) low[u]=min(low[u],dfn[v])

什么样的点是割点?

  1. 有多个儿子的根结点。
  2. 子树中不存在跨越自己连向上方的返祖边

什么样的边是桥(割边)?

  • ( u , v ) (u,v) (u,v) 是树边,且下侧的点及其子树中不存在连向上侧的返祖边,即搜索树上一结点 x x x 及其子结点 y y y 满足: d f n [ x ] ≤ l o w [ y ] dfn[x] ≤ low[y] dfn[x]low[y]

T a r j a n Tarjan Tarjan 求割点代码

def tarjan(x):
    global cnt # 当前时间戳
    cnt += 1
    dfn[x] = low[x] = cnt
    flag = 0  # 子树中不满足条件的点的数量
    for y,w in g[x]:
        if not dfn[y]:
            tarjan(y)
            low[x] = min(low[x], low[y]) # 树边更新low值
            if low[y] >= dfn[x]: # 返祖边在x下侧,只要有x就是割点
                flag += 1
                if (x != root or flag > 1): boo[x] = 1 # 如果是root,还要保证儿子数大于1
        else: low[x] = min(low[x], dfn[y]) # 非树边更新 low值

n,m = map(int, input().split())
g = [[] for _ in range(n+1)]
for _ in range(m):
    x,y = map(int, input().split())
    if x == y: continue
    g[x].append(y)
    g[y].append(x)

cnt = 0  # 用于记录当前时间戳
dfn, boo = [0]*(n+1), [0]*(n+1) # dfn:时间戳, boo:是否为割点
low = [i for i in range(n+1)]
for i in range(1,n+1):
    if not dfn[i]: 
        root = i
    	tarjan(i)

T a r j a n Tarjan Tarjan 求桥(割边)代码

这是一个求无向图桥的代码,因为是无向图所以从每个点 x x x 出发都能到其父亲结点 f a fa fa。根据 l o w low low 的计算方法, ( x , f a ) (x,fa) (x,fa) 是树上的边,且 f a fa fa 不是 x x x 的子结点,故不能用 l o w [ f a ] 来更新 l o w [ x ] low[fa]来更新low[x] low[fa]来更新low[x],但是如果只记录每个结点的父亲结点,则不能处理重边的情况,有重边时,重边也属于 x x x 的返祖边,故可以用 d f n [ f a ] dfn[fa] dfn[fa] 来更新

posted @ 2024-03-12 10:25  CH-Yu  阅读(9)  评论(0)    收藏  举报  来源