@计算图的DFN及L的算法——求图的割点
声明:文章算法原理内容来自中国科学院大学陈玉福老师主讲的《计算机算法设计与分析》课程讲义,仅供交流学习使用,侵删。
算法原理
深索数-DFN,余边
DFS(深度优先搜索)为图的遍历算法,根据图顶点的深度优先遍历顺序进行编号,并根据访问次序连边,会产生一棵深度优先搜索树,顶点u的编号为u的深索数,记为DFN(u)。
图G的深度优先深度搜索树为T,余边为{E|E∈{G-T}}。
最低搜索数-L
顶点 u 的最低深索数 L(u)定义为
L(u):=min{DFN(u), min{DFN(x)|(u,x)是 T 的余边},min{L(w)|w 是 u 的子节点} }
下面陈述L(u)的由来,涉及图论知识,请读者自行结合深度优先搜索树理解。
性质1:关于深度优先搜索树 T,图 G 的每一条边(u,v)的两个端点 u、v 之间,或 u 是 v 的祖先,或 v 是 u 的祖先,即不是平辈关系。
性质2:树 T 的根是图 G 的割点当且仅当其在 T 中至少有两个子节点;
性质3: 既不是根也不是叶的节点 u 不是 G 的割点当且仅当 u 在 T 中的每个子节点 w 都至少有一个子孙(或 w 本身)关联着一条边 e(实际上是余边),e 的另一个端点是 u 的某个祖先(e 一定是树 T 的余边);
性质4:叶节点不能是割点。
根据性质 3,4,深度优先搜索树 T 的非根节点 u 是 G 的割点当且仅当 u 至少有一个儿子 w,w 及其子孙都不与 u 的任何祖先相邻。
注意到 u 的深索数一定小于其子孙的深索数,所以深索数 DFN 并不能反映一个顶点是否是割点的情况。为此,我们递归地定义各个顶点 u 的最低深索数 L(u)。
割点的判断
如果 u 不是深度优先搜索树的根,则 u 是图 G 的割点
当且仅当
u 有某个子节点w,w 的最低深索数不小于 u 的深索数,即存在 v 的子节点 w,使得L(w)≥DFN(u)
伪代码及可执行程序
计算图的DFN及L伪代码
DFNL(u,v) //一个深度优先搜索算法,u 是开始顶点。在深度优先树中,
//若 u 有父亲,则 v 即是。数组 DFN 初始化为 0,变量 num 初始
//化为 1,n 是图 G 的顶点数。
global DFN[n],L[n],num,n
1. DFN(u):=num; L(u):=num; num:=num+1;
2. for 每个邻接于 u 的顶点 w do
3. if DFN(w)=0 then
4. DFNL(w,u); //访问 w
5. L(u):=min(L(u),L(w));
6. else
7. if w≠v then L(u):=min(L(u),DFN(w));
end{if}
8. end{if}
9. end{for}
10.end{DFNL}
java可执行程序
//使用邻接链表的数据结构表示图
import java.util.ArrayList;
public class Adjacency_List {
ArrayList<ArrayList<Integer>> nodeList;
int n;
public Adjacency_List(int n){
nodeList = new ArrayList<>();
this.n = n;
for(int i = 0; i < n; i++){
ArrayList<Integer> node = new ArrayList<>();
node