图的最短路径问题

 

BFS算法

适用性

  • 只适用于无权图, 或者是所有边的权值都相同的图

Dijkstra算法

步骤

  • 初始化: 集合S初始为{0}, dist[]的初始值为dist[i]=arcs[0][i]
  • 从顶点集合V-S中选出vj, 满足dist[j]=Min{dist[i]|vi∈V-S}, vj就是当前求得的一条从v0出发的最短路径的终点, 令S=S∪{j}
  • 修改从v0出发到集合V-S上任一顶点vk可达的最短路径的长度: 若dist[j]+arcs[j][k]<dist[k], 则更新dist[k]=dist[j]+arcs[j][k]
  • 重复2、3操作共n-1次, 知道所有顶点都包含在S中

两个辅助数组

  • dist[]: 记录从原点v0到其他各点的当前的最短路径长度. 初态是: 如果从v0到vj有弧, 则dist[i]为弧上的权值; 否则dist[i]为∞
  • path[]: path[i]表示从原点到顶点i之间的最短路径的前驱结点. 当完成该算法后, 可以根据该数组追溯得到v0到vj的最短路径

本质

  • 基于贪心策略

复杂度

  • 时间复杂度
    • 总共2、3步要循环n-1次, 时间复杂度为O(|V|)
    • 循环遍历所有的顶点, 找到dist最小且在V-S中的顶点(即步骤2), 时间复杂度为O(|V|)
    • 检查所有V-S中除dist值最小的顶点, 按照步骤3更新其最短路径的长度, 时间复杂度为O(|V|)
    • 综上所述, 该算法的时间复杂度为O(|V|)*[O(|V|)+O(|V|)]=O(|V|^2)

缺陷

  • 无法求解边上带有负权值的最短路径长度

Floyd算法

步骤

  • 初始化: 方阵A^(-1)[i][j]=arcs[i][j]
  • 将vk作为中间顶点, 对于所有的顶点对{i, j}, 如果有A(m-1)[i][j]>A(m-1)[i][k]+A^(m-1)[k][j], 则将A(m-1)[i][j]更新为A(m-1)[i][k]+A^(m-1)[k][j], 更新后的方阵记为A^(m)
  • 重复2的操作, 经过n次的迭代以后, 所得到的A^(m-1)[i][j]就是vi到vj的最短路径长度

复杂度分析

  • 时间复杂度
    • 以i作为中转结点, 时间复杂度为O(|V|)
    • 遍历矩阵, 时间复杂度为O(|V|^2)
    • 综上所述, 时间复杂度为O(|V|)*O(|V|2)=O(|V|3)

缺陷

  • 允许带有负权值的边, 但是不允许有包含负权值的边组成的回路

本质

  • 动态规划思想
  • 子问题的最优解构成整体的最优解(无需考虑两个或者多个中转结点的情况)

求解方法

单源最短路径

  • BFS算法(无权图)
  • Dijkstra算法(带权图、无权图)

各顶点间的最短路径

  • Floyd算法(带权图、无权图)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值