欢迎使用CSDN-markdown编辑器

这篇博客深入探讨了最短路径算法,包括Floyd、Bellman-Ford、Dijkstra及其优化、SPFA和A*。讲解了每种算法的工作原理、适用场景,并通过实例展示了它们在解决实际问题中的应用,如负权边处理、启发式搜索等。此外,还提到了Floyd和Johnson算法在寻找所有最短结点对上的应用。最后,博主分享了几道有趣的最短路径问题,如渡河问题、字符串变化等。
摘要由CSDN通过智能技术生成

图论报告

浅谈最短路

标签(空格分隔): 算法报告 图论 最短路


内容
  1. 最短路
    • Floyd v3
    • Bellman-ford ve
    • Dijkstra v2
    • Dijkstra Heap优化 vlogv+elogv
    • SFPA ve
    • A*
  2. 所有节点对最短路
    • 矩阵乘法 v4
    • Floyd-Warshall v3
    • Johnson * (可于负权图) v2logv
  3. 最小生成树
    • Prim v2 (邻接表 elogv
    • Kruskal eloge
  4. 具体题目

最短路大家族

Floyd ——正负权均可

这是一个耿直的,但是最容易写的代码。
本质是dp
对于只使用前 k 个点,求得最优解
那么就可以dp出 使用前 k + 1 个点的最优解
以下是dp过程

for(int k=1; k<=n; k++)   
    for(int i=1; i<=n; i++)   
        for(int j=1; j<=n; j++)   
            if(e[i][j] > e[i][k] + e[k][j])   
                e[i][j] = e[i][k] + e[k][j]; 

Bellman-ford ——正负权均可

Bellman-ford是 不断松弛 寻得最优的过程
每次对所有边松弛操作一次
可以证明,至多 v-1 次,即可求得解

for(int i=1; i<=v-1; i++)
    for(int j=1; j<=e; j++){
        int u = edge[j].u;
        int v = edge[j].v;
        int weight = edge[j].weight;
        if(dis[v] > dis[u] + weight)
            dis[v] = dis[u] + weight;
    }
// 判断是否存在负环
bool flag = 0;
for(int i = 1; i<=e; i++){
    if(dis[edge[i].v] > dis[edge[i].u] + edge[i].weight){
        flag = 1;
        break;
    }
}
// flag == 1 存在负环

Dijkstra —— 无法负权

Dij是每次通过获得最快能到达点,在以此继续贪心,来得到最短路的算法。

对于如下 n = 3 的邻接矩阵

0 2 3
2 0 -2
3 -2 0

在更新的过程中 Dis[i]的状态如下

步骤 dis1 dis2 dis[3] 过程
0 0 从点1触发
1 0 2 3 从点2触发
2 0 2 1 完毕

那么,dis2通过Dij得出的结果是 2
但是,很明显,可以通过 1->3->2的方式得到一个 1 的更优解

为什么Dij会失败呢?

Dij 是贪心,每次贪心得出(最快能到达的点)
负权会产生影响,把之前得到的某个点再次优化
但是这个被影响的点已经跑完了,就不会更新他所能影响的点

Dijkstra —— Heap 优化

Dij的算法步骤如下

  • 在未纳入的点中,获得最优点①
  • 以该点出发,更新其他点 ②

步骤① 会重复执行 v
步骤② 执行的总次数实际上所有的边 即 e
而步骤 ① 需要 获得最优点,朴素的搜索需要 v
步骤② 的更新朴素实现是 O(1)
所以总时间是 vv+e1

Dij的Heap优化在于,把获得最优点更新其他点用堆来实现
获得最优点即是删除堆顶 复杂度为 logV
更新其他点则是修改堆的节点值 复杂度为 logV
所以 Heap 优化后的Dij,时间为 vlogv+elogv
即复杂度为 O(elogv)

实际上,当

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值