看了算法导论,才知道自己理解的深搜、广搜有多肤浅。
搜索算法非常直观,容易理解。只要简单学过其思想,都能在做算法题时自己写出来,或者模板背出来。但是这些是图论算法的基础,如果不把搜索算法的方方面面研究透彻,很难再学习更难得图论算法。接下来两篇文章将探索图搜索算法的方方面面。本问将证明广度优先搜索求最短路的正确性,证明过程中会导出广搜算法中得一些重要性质。而下一篇文章将使用深度优先搜索实现强连通分量算法的正确性。
算法描述
为了全面的考察广度优先搜索算法,我们将给节点加入一些状态。
- v . c o l o r :初始状态为白色,被发现时改为灰色,其所有的邻接节点都被发现时,变为黑色。所以灰色代表被发现节点和未被发现的节点的边界。 v.color:初始状态为白色,被发现时改为灰色,其所有的邻接节点都被发现时,变为黑色。所以灰色代表被发现节点和未被发现的节点的边界。 v.color:初始状态为白色,被发现时改为灰色,其所有的邻接节点都被发现时,变为黑色。所以灰色代表被发现节点和未被发现的节点的边界。
- v . d :初始 s 节点到 v 节点的距离 ( 算法发现 v 时得到得 s 到 v 的简单路径的边的数量 ) v.d:初始s节点到v节点的距离(算法发现v时得到得s到v的简单路径的边的数量) v.d:初始s节点到v节点的距离(算法发现v时得到得s到v的简单路径的边的数量)
- v . π : v 的前驱节点,也就是说是从哪个节点发现 v 的,初始化为 n i l v.\pi: v的前驱节点,也就是说是从哪个节点发现v的,初始化为 nil v.π:v的前驱节点,也就是说是从哪个节点发现v的,初始化为nil
BFS(G, s)
for v in G.V:
v.color = white
v.d = Inf
v.Π = nil
s.color = gray
s.d = 0
s.Π = nil
que = empty
que.push(s)
while !que.empty()
u = que.pop()
for v in G.adj[v]:
if v.color == white:
v.color = gray
v.d = u.d + 1
v.Π = u
que.push(v)
u.color = black
复杂度分析
算法使用聚合分析的思想。队列中存放的是节点v。根据代码,每个节点只会入队、出队一次,所以队列操作的复杂度为 O ( V ) O(V) O(V)。此外,算法 13 行对每个节点遍历了其临接边,但所有的边只会遍历一次。因此对边的遍历的总操作的复杂度为 O ( E ) O(E) O(E),因此广度优先搜索的复杂度 O ( V + E ) O(V+E) O(V+E)
最短路径证明
为了证明方便,先定义s到v的最短距离为 δ ( s , v ) \delta(s,v) δ(s,v)时s到v的所有路径中最少的边数,相应的路径称为最短路径。对于最短路径 δ ( s , v ) \delta(s,v) δ(s,v)有一个重要的性质:给定 G = ( V , E ) G=(V,E) G=(V,E),对于任意的边 ( u , v ) ∈ E (u,v)\in E (u,v)∈E,有 δ ( s , v ) ≤ δ ( s , u ) + 1 \delta(s,v) \le \delta(s,u)+1 δ(s,v)≤δ(s,u)+1。该性质还是比较直观的:如果 δ ( s , v ) > δ ( s , u ) + 1 \delta(s,v) \gt \delta(s,u)+1 δ(s,v)>δ(s,u)+1,那么s到v的路径完全可以选择先到 u u u,再到 v v v得到一个更小值,这与 δ ( s , v ) \delta(s,v) δ(s,v)的定义矛盾。
我们将通过夹逼的方式,证明算法运行结束后, v . d = δ ( s , v ) v.d = \delta(s,v) v.d=δ(s,v),即先证明 v . d ≥ δ ( s , v ) v.d \ge \delta(s,v) v.d≥δ(s,v),再证明 v . d ≤ δ ( s , v ) v.d\le\delta(s,v) v.d≤δ(s,v)。此外,还将证明 s s s到 v v v的一条最短路径为 s s s到 v . π v.\pi v.π的最短路径加上边 ( v . p i , v ) (v.pi, v) (v.pi,v),这个结论对恢复 s s s到 v v v最短路径很重要。
- 定理1:算法结束后,
v
.
d
≥
δ
(
s
,
v
)
v.d\ge \delta(s,v)
v.d≥δ(s,v)
证明:使用数学归纳法证明。先证明基本状态成立:算法开始时, s . d = 0 = v . d = δ ( s , s ) s.d=0=v.d = \delta(s,s) s.d=0=v.d=δ(s,s),而对于其他节点, v . d = I n f v.d=Inf v.d=Inf,所以基本状态成立。考虑算法的14~18行
v.color = gray
v.d = u.d + 1
v.Π = u
que.push(v)
假设,此时
u
.
d
u.d
u.d此时满足
u
.
d
≥
δ
(
s
,
u
)
u.d\ge \delta(s,u)
u.d≥δ(s,u),再根据最短路径的性质,
δ
(
s
,
v
)
≤
δ
(
s
,
u
)
+
1
\delta(s,v) \le \delta(s,u)+1
δ(s,v)≤δ(s,u)+1,可以得到,
v
.
d
=
u
.
d
+
1
≥
δ
(
s
,
u
)
+
1
≥
δ
(
s
,
v
)
v.d = u.d+1 \ge \delta(s,u) + 1 \ge\delta(s,v)
v.d=u.d+1≥δ(s,u)+1≥δ(s,v)。
此时v被图上了灰色,不会被再次入队,因此
v
.
d
v.d
v.d不会再次改变,因此基本状态与归纳均证毕,原命题成立。
-
定理2:对于算法运行中的队列中的节点 < v 1 , . . . , v r > <v_1, ...,v_r> <v1,...,vr>,有 v r . d ≤ v 1 . d + 1 v_r.d\le v_1.d+1 vr.d≤v1.d+1,且队列中的 v i . d v_i.d vi.d单调递增
仍然使用数学归纳法。开始时,队列中只有 s s s,命题成立。
当 v 1 v_1 v1从队列中删除时,对原命题没有影响,原命题依然成立。
当 v r + 1 v_{r+1} vr+1入队时, v 0 v_0 v0刚从队列中移除。此时 v r + 1 . d v_{r+1}.d vr+1.d 被设置为 v 0 . d + 1 v_{0}.d+1 v0.d+1。- 由于 v r . d ≤ v 0 . d + 1 v_r.d\le v_0.d + 1 vr.d≤v0.d+1(上一轮的假设),所以 v r . d ≤ v r + 1 . d v_{r}.d\le v_{r+1}.d vr.d≤vr+1.d,单调性成立。
- 因为 v 0 . d + 1 ≤ v 1 . d + 1 v_0.d +1 \le v_1.d +1 v0.d+1≤v1.d+1 (上一轮的单调性假设),因此 v r + 1 . d ≤ v 1 . d + 1 v_{r+1}.d \le v_1.d +1 vr+1.d≤v1.d+1。因此基本状态和归纳均成立,命题得证。
-
推论2.1:算法运行中,当 v i v_i vi在 v j v_j vj之前入队时,必有 v i . d ≤ v r . d v_i.d\le v_r.d vi.d≤vr.d,d 随着算法的运行单调递增的。
定理2已保证了这一点
-
定理3: v . d = δ ( s , v ) v.d = \delta(s,v) v.d=δ(s,v),并且v的最短路径为 v . π v.\pi v.π的最短路径加边 < v . π , v > <v.\pi, v> <v.π,v>
使用反证法:假设算法结束后,有一些 v . d v.d v.d 不满足 v . d ≠ δ ( s , v ) v.d \neq \delta(s,v) v.d=δ(s,v)。我们精心挑选一个 v v v,他是所有 v . d ≠ δ ( s , v ) v.d \neq \delta(s,v) v.d=δ(s,v)的节点中, δ ( s , v ) \delta(s,v) δ(s,v)最小的一个。根据定理1,可知 v . d > δ ( s , v ) v.d > \delta(s,v) v.d>δ(s,v)。假设节点 u u u为 s s s到 v v v的最短路径上, v v v的直接前驱节点。因此 δ ( s , v ) = δ ( s , u ) + 1 \delta(s,v)= \delta(s,u) + 1 δ(s,v)=δ(s,u)+1,即 δ ( s , u ) < δ ( s , v ) \delta(s,u) \lt \delta(s,v) δ(s,u)<δ(s,v)。 因为 v v v是 v . d ≠ δ ( s , u ) v.d\neq \delta(s,u) v.d=δ(s,u)的最小节点,因此 u . d = δ ( s , u ) u.d = \delta(s,u) u.d=δ(s,u)。于是有不等式
v . d > δ ( s , v ) = δ ( s , u ) + 1 = u . d + 1 v.d\gt \delta(s,v) = \delta(s,u) + 1 = u.d + 1 v.d>δ(s,v)=δ(s,u)+1=u.d+1
考虑 u u u 从队列 Q Q Q中取出的时间。此时 v v v 可以是任何颜色。- 如果 v v v是白色,那么本轮循环会将v.d设置为u.d + 1,与 v . d > δ ( s , v ) = δ ( s , u ) + 1 v.d\gt \delta(s,v) = \delta(s,u) + 1 v.d>δ(s,v)=δ(s,u)+1矛盾。
- 如果 v v v是灰色,那么 v v v此时在队列中,根据定理2, v . d ≤ u . d + 1 v.d \le u.d +1 v.d≤u.d+1,依然与上式矛盾
- 如果 v v v是黑色,那么 v v v此时已经不在队列中,根据推论2.1, v . d ≤ u . d v.d \le u.d v.d≤u.d,仍然矛盾。
因此算法结束后 v . d = δ ( s , v ) v.d= \delta(s,v) v.d=δ(s,v)。根据算法伪代码,如果 v . π = u v.\pi=u v.π=u,则必有 v . d = u . d + 1 v.d = u.d + 1 v.d=u.d+1,即 δ ( s , v ) = δ ( s , u ) + 1 \delta(s,v)= \delta(s,u) + 1 δ(s,v)=δ(s,u)+1,因此, v v v的最短路径为 u u u的最短路径加边 < v . π , v > <v.\pi, v> <v.π,v>,证毕。文章来源:https://www.toymoban.com/news/detail-510478.html
广度优先树
根据广度优先搜索算法的性质,算法结束后,可以通过每个节点的 v . π v.\pi v.π属性来恢复最短路径。事实上使用 v . π v.\pi v.π属性为边,加上其关联的节点,可以形成一个树形结构。称之为:广度优先树 G . π G.\pi G.π文章来源地址https://www.toymoban.com/news/detail-510478.html
到了这里,关于【算法证明 六】深入理解广度优先搜索的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!