无向图的割顶和桥

来源:互联网 发布:时间校准软件 编辑:程序博客网 时间:2024/04/28 14:47
对于无向图G, 如果删除某个点u后, 连通分量数目增加, 称u为图的
关节点(
articulation vertex) 或割顶(cut vertex) 。 对于连通图, 割顶就
是删除之后使图不再连通的点。
如何求出图的所有割顶呢? 我们有两个选择。
选择一: 尝试删除每个结点, 然后用
DFS判断连通分量是否增加, 时
间复杂度为
Onnm) ) , 其中nm分别是图中的点数和边数。
选择二: 深入挖掘
DFS的性质, 在线性时间( 即Onm) 时间) 内
求出所有割顶。
毫无疑问, 第二个选择比
删除-测试的方法高效许多, 并且达到了
理论下界, 是理想的方案。 下面我们就来学习这个方法。
时间戳。 本节的算法依赖于
时间戳这个概念。 反应到代码中, 只需
PREVISITu) 和POSTVISITu) 中加如下代码, 就可以为每个结点记
录两个时间戳。
其中, 全局的
当前时间”dfs_clock初始化为0。 不难发现, 当所有结
点都访问过以后,
dfs_clock的值将等于2m
如图
5-4所示是一个无向图和对应的DFS森林, 每个结点u均标记以
459
pre[u]post[u]。 强烈建议读者根据自己的理解模拟DFS过程, 看看是否
能得到相同的
DFS森林。 执行dfsu) 时, 应当按照字母从小到大的顺序
考虑
u的各个子结点。
5-4
边分类。 注意无向图的每条边( uv) 会处理两次: 访问u的时候一
次, 访问
v的时候一次。 DFS森林中的边称为树边( tree edge) 。 第一次处
理时从后代(
descendant) 指向祖先(ancestor) 的边称为反向边(back
edge
) 。 在无向图中, 除了树边之外, 其他边都是反向边。 有向图除了树
边和反向边外还有前向边(
forward edge) 和交叉边(cross edge) , 这里
不再赘述。
割顶和桥的条件。 简单起见, 我们只考虑连通图。 在这样的情况
下,
DFS森林一定只有一棵树。 树根是不是割顶呢? 不难发现, 当且仅当
它有两个或更多的子结点时, 它才是割顶
——无向图只有树边和反向
边, 不存在跨越两棵子树的边。 对于其他点, 情况就要复杂一些。 我们
有下面的定理。
定理: 在无向连通图
GDFS树中, 非根结点uG的割顶当且仅当u
存在一个子结点v, 使得v及其所有后代都没有反向边连回u的祖先( 连回u
不算) 。
证明: 如图
5-5所示, 考虑u的任意子结点v。 如果v及其后代不能连
f, 则删除u之后,fv不再连通; 反过来, 如果v或它的某一个后代存
在一条反向边连回
f, 则删除u后, 以v根的整棵子树中的所有结点都可以
利用这条反向边与
f连通。 如果所有子树中的结点都和f为连通, 根据
关系的传递性, 整个图就是连通的。
460
5-5
方便起见, 设lowu) 为u及其后代所能连回的最早的祖先的pre值,
则定理中的条件就可以简写成结点
u存在一个子结点v, 使得lowv
≥preu) 。
作为一种特殊情况, 如果
v的后代只能连回v自己( 即lowv) >
preu) ) , 只需删除(uv) 一条边就可以让图G非连通了, 满足这个
条件的边称为桥(
bridge) 。 换句话说, 我们不仅知道结点u是割顶, 还
知道了(
uv) 是桥。
注意对于每个割顶或者桥来说, 上述条件可能不止成立一次, 所以
一般不要边判定边输出, 而是用数组来记录每个结点是不是割顶, 以及
每条边是不是桥, 最后一次性输出。
low函数的计算。 现在唯一的问题是low函数本身的计算, 它可以用
下面的代码来递推计算。 注意, 代码中已经加入了割顶的判断, 桥的判
断留给读者。
461
每次递归访问结束时, 该结点的low函数就被正确计算出来了。 在上
面的代码中, 最容易写错的是, 漏掉
v不等于fa的判断。 边(ufa) 不是
反向边, 而是树边(
fau) 的第二次访问。 在调用这个代码之前不要忘
记把所有结点的
pre初始化为0, 且第一次调用时,fa的值应该等于负数。
0 0