算法设计与分析课程复习笔记9——图的算法(含BFS、DFS)

算法设计与分析课程复习笔记9——图的算法(含BFS、DFS)

图的算法

图:物体与物体之间的连接关系
图的背景知识

  • 图:节点+边
  • 表示方法:图G=(V,E)
  • 节点V,|V|=n,节点数目
  • 边E,|E|=m,边数目

图的其他类型:连通图(如果任何两个顶点之间存在一个通路,则称图是连接的),
二分图(无向图,由 V 1 V_1 V 2 V_2 组成,只在 V 1 V_1 V 2 V_2 之间的顶点存在边)

图的表示方法
邻接表
邻接表

  • 特性:有向图:邻接表长度的和等于边的数目
    无向图:邻接表长度的和等于两倍的边的数目
  • 空间需求:Θ(V+E)
  • 适合:|E|<<|V|2
  • 缺陷:不容易判断顶点u和v之间是否存在边
  • 罗列与u邻接顶点的时间开销:Θ(degree(u))
  • 判断(u, v) ∈ E的时间:O(degree(u))

相邻矩阵

  • 无向图的相邻矩阵具有对称性
  • 空间需求:Θ(V2),与边无关
  • 适合情况:|E|接近|V|2,需要快速确定两个顶点之间是否存在边
  • 罗列与u邻接顶点的时间开销:Θ(V)
  • 判断(u, v) ∈ E的时间:Θ(1))

有权图
图的边被赋予了权值
权的存储:邻接表:存储在边表表目中。相邻矩阵:存储在元素中。

图的遍历
两种基本搜索算法

  • 广度优先搜索
  • 深度优先搜索

广度优先搜索BFS

  • 输入:图G = (V, E),有向或无向。源顶点s ∈ V
  • 目的:从临近源顶点s最近的顶点开始,通过对图G的边的探索发现从源顶点s能够抵达的每个顶点
  • 输出:从s到v的距离d[v]。广度优先树:以s为根,包含所有可以抵达的顶点

广度优先:距离源顶点的距离逐渐增加来搜索相连通的其它顶点
广度优先
过程追踪:

  • 用白、灰和黑来标记顶点
  • 最初为白
  • 刚搜索到,灰
  • 所有邻接顶点被搜索完,黑
  • 先进先出队列来保存灰色顶点
    过程追踪
    广度优先树BFT
  • 源节点为树根
  • 在搜索顶点u的临接顶点时一旦发现了顶点v,便将顶点v和边(u,v)加入到树中
  • 在BFT中,u是v的父节点
  • 一个顶点只被发现一次,因此只有一个父节点

BFS附加数据结构

  • 邻接表法表示图G=(V,E)
  • 顶点颜色color[u]
  • 顶点u的父顶点π[u]
  • 如果顶点是根顶点或没有被发现,父顶点为空。π[u] = NIL
  • 从s到u的距离d[u]
  • 应用FIFO队列Q存储灰色顶点

BFS算法
for each u ∈ V-{s}
 do color[u] ← WHITE
  d[u] ← \infty
  π[u] ← NIL
color[s] ← GRAY
d[s] ← 0
π[s] ← NIL
Q ← 空集
Q ← Enqueue(Q,s)
while Q ≠ 空集
 do u ← Dequeue(Q)
  for each v ∈ Adj[u]
   do if color[v] = WHITE
    then color[v] = GRAY
      d[v] = d[u]+1
      π[v] = u
      Enqueue(Q,v)
  color[u] ← BLACK

广度优先搜索
算法分析:
BFS1
BFS2
最短路径
BFS确定了从源节点到其他顶点的最短路径

深度优先搜索DFS

输入:图,没有源顶点G(V,E)
目的:从当前访问顶点开始,探索图的边以发现图中的每个顶点
搜索从多个源重复
输出:每个顶点有两个时间标记:发现时间d[v],结束时间(检查v所有的邻接表)f[v]
深度优先森林DFF

扫描二维码关注公众号,回复: 10004584 查看本文章

深度优先搜索

  • 尽可能往深度搜索
  • 最近发现的顶点v仍然有没有被搜索的边
  • 顶点v的所有边搜索完后,回朔到v的父顶点搜索
  • 这个过程不断继续,直到从源顶点可以抵达的所有顶点都被发现
  • 如果图中存在还没有发现的顶点,选择其中之一作为新的源顶点重复上述搜索过程
  • 深度优先搜索DFS产生的是深度优先森林

DFS附加数据结构

  • 全局变量:时间步骤。在顶点发现和搜索完成时增加
  • 颜色变量color[u],和BFS类似。白:发现前,灰:发现处理中,黑:处理完成
  • 顶点u的父顶点π[u]
  • 发现、完成时间d[u]、f[u]

DFS算法:
DFS(V,E)
for each u ∈ V
 do color[u] ←WHITE
  π[u] ← NIL
time ← 0
for each u ∈ V
 do if color[u] = WHITE
  then DFS-VISIT(u)

DFS-VISIT(u)每次被调用时, u就成为深度优先森林中一棵新树的根节点

DFS-VISIT(u)
color[u] = GRAY
time ← time + 1
d[u] ← time
for each v ∈ Adj[u]
 do if color[v] = WHITE
   then π[v] = u
     DFS-VISIT(v)
color[u] = BLACK
time ← time + 1
f[u] = time

深度优先搜索
深度优先搜索2
边的类型

  • 树边:抵达白色顶点。
    边(u, v) 是一树边,如果v是在探索边(u, v)时首次被发现
  • 回边:抵达灰色顶点。
    边(u,v)连接顶点u至其一个深度优先树的先辈顶点v
    有向图中的自回路也是回边
  • 前向边:抵达黑色顶点,且d[u]<d[v]
  • 横跨边:抵达黑色顶点,且d[u]>d[v]

算法分析:
DFS1
DFS2
DFS特性

  • u = π[v] \leftrightarrow DFS-VISIT(v) 在搜索u的邻接表时被调用
  • 深度优先树上顶点v是顶点u的后裔 \leftrightarrow 顶点v在顶点u处于灰色状态时被发现
  • 顶点v是顶点u的后裔 \leftrightarrow d[u] < d[v] < f[v] < f[u]
  • 在图G的任何深度优先森林中,顶点v是顶点u的后裔,当且仅当在时刻d[u],存在一条u → v的路径只包含有白色顶点

括号定理
对于一个图的任何DFS,对于任何u,v,下列情况之一成立:

  1. [d[u], f[u]]和[d[v], f[v]]不邻接, u和v 互不为后裔
  2. [d[u], f[u]] 包含[d[v], f[v]], v是u的后裔
  3. [d[v], f[v]] 包含[d[u], f[u]] , u是v的后裔

拓扑排序

拓扑排序:找出有向无回路图G = (V, E)中顶点的一个线性序,使得(u, v)如果是图中的一条边,那么在这个线性序中u在v前出现

顶点水平排列,有向边从左到右。

TOPOLOGICAL-SORT(V, E)

  1. 调用DFS(V, E) ,对每个顶点v计算其完成时间f[v]
  2. 顶点完成,将之插入到连接表前端
  3. 返回顶点的连接表

运行开销: Θ ( V + E ) Θ(V + E)

引理:有向图是无回路的 \leftrightarrow 深度优先搜索DFS不产生回边

强连通分支SCC
有向图G = (V, E)中的强连通分支是它的顶点的极大集C(V的子集) ,在该集中,每一对顶点u, v ∈ C有u → v 和v → u
强连通分支
图的转置
GT是G的所有边转向
应用邻接表,我们可以在 Θ ( V + E ) Θ(V + E) 时间创造GT

GT和G有相同的SCC

有向无回路图的SCC确定方法:在G和GT做深度搜索

强连通分支的求解

  1. 在图上执行深度优先搜索,计算每个顶点u的完成时刻f[u]
  2. 构成转置图GT
  3. 从具有最大f[u]的顶点开始,在GT上执行深度优先搜索,如果深度优先搜索不能到达所有的顶点,则在余下的顶点中找一个f[u]最大的顶点,开始下一次深度优先搜索
  4. 在最终得到的森林中的每一棵树对应一个强连通分支

强连通分支求解
分支图
分支图
两个引理

  1. C和C’是图G的SCC,u, v ∈ C,u,v∈ C,假设图G中存在通路u → u,则不可能存在v→ v
  2. C和C’是有向图G = (V, E)的SCC,如果存在边(u, v) ∈ E ,u ∈ C, v ∈ C’,则有f(C) > f(C’)

参考:任课教师邱德红教授的课件

发布了25 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42605042/article/details/89790277