Lec 10深度优先搜索
Lec 10 深度优先搜索
资料依据:课程视频与 transcript · Lecture notes
TL;DR
- DFS 沿一条未访问边尽可能深入,再回溯处理其他分支;整个遍历依然只需 时间。
- 对所有未访问顶点启动 DFS 可得到一片森林,并用完成顺序揭示连通性与依赖结构。
- 有向图在无环时,顶点按 DFS 退出时间的逆序构成拓扑序;遇到指向当前递归栈的边则证明存在环。
背景: 可到达性问题

策略:设 P(s) = None, 然后运行 visit(s)
visit(u):
for every v ∊ Adj(u):
if P(v) = None:
Set P(v) = u
Call visit(v)
DFS
- 类似于 BFS,从 s 开始搜索图
- 解决单源可达性问题,而不是单源最短路径问题(sP)
- 返回指向 s 的父指针树
- 思路是: 递归访问出边的邻接顶点,但不重新访问同一个顶点,即沿着任何路径前进直到无法前进,然后回溯直到找到一条未探索的路径继续探索
正确性证明
- 断言: DFS 访问顶点 v 并正确设置 P(v),对于从 s 可达的每个顶点 v 都成立
- 证明: 对 k 进行归纳,只对距离 s 为 k 的顶点进行断言
- 基本情况(k=0): P(s) 被正确设置为 s 并被 s 访问
- 归纳步骤,考虑顶点 v 满足
- 考虑顶点 u,即从 s 到 v 的某条最短路径上的倒数第二个顶点(即 v 前一个顶点)
- 根据归纳假设,由于, DFS 访问 u 并正确设置 P(u)
- 在访问 u 时,DFS 考虑要么已经在 P 中,已被访问(即 P(u) null),要么 v 会在访问 u 时被访问,无论那种情况, v 都被 DFS 访问并正确添加到 P 中
分析
- 算法最多访问每个顶点一次,并且对于每个顶点 只花费 O(1)时间
- 工作量的上界为
- 不同于 BFS, DFS 并不返回每个顶点的距离,因此 DFS 的运行时间为 O(|E|)
全量 BFS/DFS
- 假设我们想要搜索整个图,而不仅仅是从一个顶点可达的顶点
- 思路是,对任务未访问的顶点重复执行图搜索算法 A
- 重复以下步骤,知道所有顶点都被访问
- 选择一个未访问的顶点 s,使用 A 搜索从 s 可达的所有顶点
- 我们称这个算法为 Full-A 算法
- 每个顶点访问一次,所以 Full-BFS 和 Full-DFS 的运行时间均为 O(|V|+|E|)
图的连通性
- 一个无向图是连通的,如果图中每对顶点之间都有一条路径连接。
- 在有向图中,顶点 u 可能从顶点 v 可达,但 v 可能从 u 不可达。
- 对于有向图,连通性更加复杂(我们在本课中不会讨论)。
- Connectivity(G):无向图 G 是否连通?
- Connected Components(G):给定无向图 G = (V, E),返回 V 的划分为子集 (连通分量),其中每个 在 G 中是连通的,并且不同连通分量的顶点之间没有边。
- 考虑一个解决单源可达性问题的图算法 A。
- 断言:A 可以用来解决连通分量问题。
- 证明:运行 Full-A。对于每次运行 A,将访问到的顶点放入一个连通分量中。
拓扑排序
- 有向无环图(DAG,Directed Acyclic Graph)是一个不包含有向环的有向图
- 图 G = (V, E) 的拓扑排序是对顶点的一个排序,使得每条边满足
- 拓扑排序不是唯一的。
- 证明一个有向图, 当且仅当它是一个 DAG 时,才存在拓扑排序。(练习)
- 如何找到拓扑排序?
- 结束顺序是全量 DFS 完成访问每个顶点的顺序
- 断言: 如果 G=(V, E)是一个 DAG,则结束顺序的逆序是一个拓扑排序
- 证明: 需要证明对每条边而言, u 被排到 v 之前,即访问 v 完成的时间在访问 u 之前。分两种情况
- 如果 u 在 v 之前被访问
- 在访问 u 完成之前,会访问 v(通过边(u, v)或者其他方式)。
- 因此访问 v 完成的时间在访问 u 之前
- 如果 v 在 u 之前被访问
- 由于图是无环的,u 不能从 v 过来
- 因此访问 v 完成的时间在 u 之前
- 如果 u 在 v 之前被访问
循环检测
如果图 G=(V, E)是无环的,Full-DFS 将找到一个拓扑排序,那如果 Full-DFS 的逆结束顺序不是拓扑排序,则 G 必定包含一个环。
- 检查 G 是否无环: 对于每条边(u, v),检查在逆结束顺序中,v 是否在 u 之前
- 可以通过哈希表或者是直接访问数组在 O(|E|)时间内完成
- 要返回这样的一个环,在 Full-DFS 中维护路径上回到 s 的前驱集合
- 断言: 如果 G 包含一个环,Full-DFS 将遍历从 v 到 v 的前驱的边
- 证明: 考虑 G 中有一个环
- 不失一般性地,假设是 Full-DFS 在环上访问的第一个顶点,对于每个,在访问完成之前,将访问并完成访问,考虑边,如果尚未被访问,他将访问被现在访问。因此在访问完成之前,将第一次访问(根据对的假设),所以在访问完成之前,将考虑边,其中是的前驱
我的理解
我的理解
BFS 保留的是距离层次,DFS 保留的是嵌套时间区间。后者不直接给无权最短路,却能把“先完成谁”变成拓扑顺序和环检测的证据。