算法导论【图算法】—最小生成树、最短路径、最大流算法总结

40 篇文章 6 订阅

最小生成树

Kruskal 算法

  • 思路: 寻找安全边的方法是,在所有连接森林中两棵不同树的边里面,寻找最小的边 ( u , v ) ( u , v ) (u,v)
  • 时间复杂度:时间复杂度为O(ElgV)
  • 主要取决于边数,适合稀疏图。

Prim算法

  • 思路:Prim 算法具有一个性质是集合A中的边总是构成一棵树。这棵树从某一顶点 r 开始,每一次扩展所加入的边必须是使得树的总权重增加最少的边,最终形成图的一棵最小生成树。
  • 时间复杂度:O(ElgV)[二叉堆], O(E+VlgV)[斐波那契堆][DecreaseKey操作]
  • 与图中的边数无关,适合稠密图。

单源最短路径

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Bellman-Ford算法:

  • 顶点为V,边为E的图
    1. 对每条边松弛|V|-1次
    2. 边权可以为负值
    3. 若存在一个可以从源结点到达的权值为负值的环路,算法返回False
    4. 时间复杂度:O(VE)

DAG-SHORTEST-PATHS

  • 有向无环图单源最短路径
    1. 算法首先对有向无环图进行拓扑排序
    2. 即使存在权值为负的边,也因为没有权值为负的环路,最短路径是存在的
    3. 时间复杂度: O ( V + E ) O(V+E) O(V+E) 对于邻接表表示的图,这个时间为线性级

Dijkstra算法

  • 顶点为V,边为E的图
    1. 对每条边仅松弛1次
    2. 边权不可为负
    3. 运行过程维护一组结点集合S
    4. 使用贪心策略,每次选择集合V-S中最“近”的结点加入集合S
    5. 利用结点编号维持最小优先队列,时间复杂度为:O(V2+E)=O(V2)
      • 如果是稀疏图,可以利用二叉堆实现最小优先队列,时间复杂度:O(ElgV)
      • 利用斐波那契堆实现最小优先队列,时间复杂度:O(VlgV+E)

所有结点对的最短路径问题

Floyd-Warshall算法

  • 顶点为V,边为E的图
    1. 使用动态规划公式解决所有结点对最短路径问题

    2. 时间复杂度:O(V3)

    3. 可以有负权值的边,但不可以有负权值环路

    4. 在这里插入图片描述

    5. 在这里插入图片描述

    6. δ ( i , j ) δ(i,j) δ(i,j)表示结点 i i i到结点 j j j的最短路径权重
      在这里插入图片描述

Johnson算法

  • 用于稀疏图
  1. 要么返回一个包含所有结点对的最短路径权重的矩阵,要么报告输入图包含一个权重为负值的环路
  2. 通过重新赋值来生成非负权重(不改变最短路径), h : V → R h:V\rightarrow R h:VR为任意函数:将结点映射到实数上, w ^ ( p ) = w ( p ) + h ( v 0 ) − h ( v k ) \hat{w}(p)=w(p)+h(v_0)-h(v_k) w^(p)=w(p)+h(v0)h(vk)
  3. 重新赋值不改变环路的权重
  4. 对图进行预处理,在O(VE) 时间内计算出新权重 w ^ \hat{w} w^
  5. 时间复杂度:斐波那契堆:O(V2lgV+VE),二叉最小堆:O(VElgV)
  6. 运行中需要使用Dijkstra算法和Bellman-Ford算法作为自己的子程序

最大流

增广路径是残存网络中一条从源点s到汇点t的简单路径
在这里插入图片描述

Ford-Fulkson算法

  1. 算法运行时间取决于如何找到增广路径
  2. f ∗ f^* f表示转换后网络的一个最大流,则运行时间为 O ( E ∣ f ∗ ∣ ) O(E|f^*|) O(Ef)
  3. 使用BFS或者DFS在残存网络找一条增广路径的时间为 O ( V + E ) O(V+E) O(V+E)

Edmonds-Karp算法

  1. 使用广度优先搜索BFS寻找增广路径的Ford-Fulkerson方法就是Edmonds-Karp算法
  2. 运行时间:O(VE2)
  3. 运行在流网络G=(V,E)上,算法执行的流量递增操作总次数为 O ( V E ) O(VE) O(VE)

例题

  1. 我们怎样才能使用 Floyd-Warshall 算法的输出来检测权重为负值的环路?
    若图中有负环,假设节点 i 为负值环路中的一个节点,在循环中会更新节点 i 到自身的距离,对于大于负值环路中的所有节点序号k,会使得 d i i k d_{ii}^k diik为负值。

  2. 假定在一个权重函数为 W 的有向图图 G 上运行 Johnson 算法。
    证明:如果图 G 包含一条权重为0 的环路 c,那么对于环路 c 上的每条边 (u, v),
    w ^ ( u , v ) = 0 \hat{w}(u,v)=0 w^(u,v)=0
    由于重新赋值不会改变环路的权重,故重新赋值后此环路的权重仍为0,又由于重新赋值后每条边的权重为非负权重,故对于环路 c 上的每条边 (u, v),有 w ^ ( u , v ) = 0 \hat{w}(u,v)=0 w^(u,v)=0

  3. 给定 G = (V,E) 是一带权重且没有权重为负值的环路的有向图,对于所有的结点 v ∈ V,从源结点 s到结点 v 之间的最短路径中,包含边的条数的最大值为 m。请对算法 BELLMAN-FORD 进行简单修改,可以让其在 m+1 遍松弛操作之后终止,即使 m 不是事先知道的一个数值。
    用一个数组记录每次循环中每个节点的v.d值,若在本轮循环中发现所有节点的v.d值较上一轮均不变,则跳出循环,算法结束。在这里插入图片描述

  4. 请举出一个包含负权重的有向图,使得 Dijkstra 算法在其上运行时将产生不正确的结果。为什么在有负权重的情况下,这一定理的证明不成立?
    在这里插入图片描述
    Dijkstra将认为s到u的最短路径长度为2而不是1。
    在这里插入图片描述
    假设 x , y x,y x,y s → u s\rightarrow u su的最短路径上的两个结点,且s,x已经在集合S中,当对x的邻居结点y进行松弛操作时, y . d = δ ( s , y ) y.d=δ(s,y) y.d=δ(s,y),但由于有负边存在,此时 δ ( s , y ) ≤ δ ( s , u ) δ(s,y)≤δ(s,u) δ(s,y)δ(s,u)不成立,即 y . d ≤ u . d y.d≤u.d y.du.d不成立,则定理的证明不成立

  5. 假定图中的边权重全部为整数,且在范围 1 ∼ |V| 内,在此情况下,Kruskal 算法最快能多快?如果变得权重取值范围在 1 到某个常数 W 之间呢?
    边权重是 到 范围内的整数,我们可以通过使用计数排序在线性时间内按权重对边进行排序,从而使 Kruskal 算法在O(Eα(V)) 时间内运行。 如果边权重是由常数限定的整数,可以采用相同的方法,因为运行时算法需要决定边是否加入不相交的森林,而这与边的权重无关。
    在这里插入图片描述

  6. 假定图中的边权重全部为整数,且在范围 1 ∼ |V| 内,在此情况下,Prim 算法最快能多快?
    先选择一个顶点作为树的根节点,把这个根节点当成一棵树,选择图中距离这棵树最近但是没有被树收录的一个顶点,把他收录在树中,并且保证不构成回路,按照这样的方法,把所有的图的顶点一一收录进树中。使用 vEB 树来处理 Prim 算法中的优先队列这一问题的时间复杂度为O(EloglogV)

  7. 在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之墨_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值