DFS 及其相关证明

DFS 对个人来讲真是个奇怪的遍历算法,但最后再仔细看来却是相当重要的算法,难怪在CLRS的chapter notes中讲到由Hopcroft和Tarjan首先意识到DFS的重要性,记住Tarjan这个人,他在图论上有着相当大的贡献,而且首次引入了amortized analysis(分摊分析),这两位同时获得了图灵奖。DFS如此重要,以下几乎全翻译自CLRS,包括部分习题的解答。

 

顾名思义,DFS就是深度优先搜索,先尽可能的找一条包含足够多点的简单路径,如果找不到再向上一层结点回溯,DFS过程可以使用递归函数方便的实现。DFS中对于每一个点u,有一个发现时间d(u)和结束时间f(u),可以认为点u的生存周期为(d(u), f(u))。

定理1:图G=(V,E)中任意两个点u、v的生存周期均不相交,即只有相离、包含两种关系。这称为DFS的括号匹配。

证明:不失一般性,假设 d(u) <d(v),分两种情况:

(1) d(v) <f(u),发现点v时点u为灰色,由DFS过程可知v为u的子孙结点,如此便有d(u) < d(v) < f(v) < f(u),此时两点为包含关系。

(2) d(v) >f(u),则显然有 d(u) < f(u) < d(v) < f(v),此时两点为相离关系

由此定理有DFS 中v为u的子孙结点  当且仅当 d(u) < d(v)< f(v) < f(u)

 

定理2:DFS 中v为u的子孙结点  当且仅当访问到u时存在一条从u到v的白色路径,故此定理又称为白色路径定理。

这个定理如此重要,后续很多结论都需要这个条件。证明:

(1) 访问u时,u到v的路径上全是白色结点

假设此时v不是u的子孙结点,找u到v路径上第一个不是u子孙结点的结点,设为x,其父结点设为w(w可能和u相同,也可能是u的子孙结点),于是有f(u)>= f(w),由于点x假设不是u的子孙结点,故d(x)>f(u),但注意点x不可能在f(w)时刻还没有被发现,因为w=>x有一条路径,于是有d(x) < f(w),即d(x) > f(u) >=f(w) >d(x),矛盾,故假设不成立,即在u到v的路径上全是u的子孙结点。

(2) DFS过程后,v为u的子孙结点,根据括号匹配定理,u到v的路径上的任意结点x,都有d(u) < d(x) < f(x) < f(u),故当发现结点u时结点x必定为白色结点。

 

定义:DFS边的分类

tree:      DFS树的边

back:      DFS树中从某结点到其祖先结点的边

forward:          DFS树中从某结点到其子孙结点的边

cross:      其他结点,可以从一棵DFS树到另一棵DFS树的边,也可以同一个DFS树内没有没有祖先关系的边

刚开始觉得边的分类极其无聊,后续在做题过程才发现有实际意义。

 

定理3,DFS无向图,只有tree、back边

证明,任意边u<=>v,不失一般性,假设d(u)< d(v),根据白色路径定理v为u的子孙结点,于是不可能为cross边。如果第一次访问边是从u发起时,则v必定为白色,于是边为tree边;如果第一次访问边是从v发起时,则为back边

 

22.3-7 举出一个反例。有向图,当u到v有一条路径,而且d(u)< d(v),则v为u的子孙结点。

u <==> x ==>v

如上,从x开始DFS,先选择u,再选择v,则有d(u) <d(v),但是v不是u的子孙结点

你可能感兴趣的:(DFS 及其相关证明)