深度优先搜索可以用来实现“对有向图图中环的存在与否检测”,无向图环与否也差不多这样,但是这里主要是有向图。
在【图论】广度优先搜索和深度优先搜索中,“《算法导轮》对两种搜索都采用了很聪明的做法”,两种算法都标记了颜色。在深度优先搜索算法中,
-
WHITE 未访问顶点
-
GRAY 一条深度搜索路径上的顶点,即被发现时
-
BLACK 此顶点的邻接顶点被全部访问完之后——结束访问次顶点
有向图的搜索过程
一个图的深度优先搜索过程:
在未探索完的一条深度优先搜索路径上,这条路径上的所有点都是灰色的(如果这些点被访问);而搜索过程又不是并行的,所以程序每次只处在一条深度优先搜索路径的处理上。不知道理解没有,来看看图:
更形象点,介绍一下“DFS树”,在DFS过程当中,把真正走过的边加入DFS树当中,那些未真正走过的边不加入到DFS树当中,比如,从u到已经被访问的v,那么(u,v)就是一条未真正走过的边。来看图:红色边和其所连接的点组成了DFS树,在图中,DFS树会有两棵。
如果这样来定义DFS树的话,那么在这课DFS树当中只有树边了。
树边和反向边定义
树边的定义:如果顶点v在探寻边(u,v)边时候被首次发现的,那么(u,v)就是树边。
再来一个反向边的定义:
反向边:在DFS树中,连接顶点u到它某一祖先顶点v的边,也就是连接到那DFS条路径上点的边。
上面的两个图是等价的。
所以如果这么定义深度优先搜索树,对于下面的图它不可能存在反向边了,只有树边。把DFS树稍作修改,就可以得到原图(加上反向边,正向边,交叉边,《导论》有概念),
对于有向图,判断有无环就是判断它的“DFS树是否存在反向边”?那么如何判断呢?利用“颜色标记”法,就可以很简单做到。
上面的虚线边就表示当前DFS路径上探索到了一条反向边因为x和z点都是灰色的。当然对于有向图中是否存在环,并不影响DFS的最终效果——遍历。
于是有伪代码:
DFS(G,s)
for each vertex v in V(G)
status[v] = WHITE
/******其他初始化******/
for each vertex v in V(G)
if(status[v]==WHITE)
if !DFS-VISIT(v) = false
return false
DFS-VISIT(v)
status[v] = GRAY
for each vertex t in Adj(v)
if status[t] = WHITE
DFS-VISIT(t)
else if status[t] = GRAY
return false
/******其他操作******/
status[v] = BLACK
所以核心就是判断反向边的问题。
本文完 2012-05-19
Dylan http://daoluan.github.io/blog
19 May 2012 会持续更新