首页 > 编程语言 >最短路三种算法详解

最短路三种算法详解

时间:2023-08-26 20:34:12浏览次数:39  
标签:ver int 短路 st 算法 详解 短距离 dist include

最短路

最短路问题即,给你一张图,让你求出图中两点的最短距离。

这篇文章会讲解 \(Dijkstra\)、\(Spfa\)、\(Floyd\) 三种算法,让您透彻理解最短路!

Dijkstra

朴素版

题目:

image

\(Dijkstra\) 通常是用来解决图中一个定点到其余点的最短距离,基本思路是:从中心向外扩展,直到扩展到终点为止。

我们用 \(dist[u]\) 来表示从源点 \(s\) 到 \(u\) 的最短距离。

还需要维护一个状态数组 \(st\),用于在更新最短距离时,判断当前的点的最短距离是否需要更新(是否已经确定)。

在每一次扩展的过程中,我们要先找到当前未确定的点的集合中找到一个距离最小的点,也就是:

int t = -1; // 距离最短的点的编号
for (int j = 1; j <= n; ++j) 
    if (!st[j] && (t == -1 || dist[j] < dist[t])) // 判断是否符合条件
        t = j;

那么我们就已经确定这个点了,把它的状态更新一下:

st[t] = true;

然后用这个点更新所有未确定点的最短距离

for (int j = 1; j <= n; ++j) 
    if (!st[i]) // 这句话其实可以不用加,因为我们dijkstra算法的性质已经确定后面确定的点不会再比现在的小了
        dist[j] = min(dist[j], dist[t] + g[t][j]);

完整代码:

#include <iostream>
#include <cstring>
#define N 510
using namespace std;
int n, m;
int g[N][N];
int dist[N];
bool st[N];
int dijkstra() {
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0; // 源点到源点的距离是0
    for (int i = 1; i <= n; ++i) {
        int t = -1;
        for (int j = 1; j <= n; ++j) 
            if (!st[j] && (t == -1 || dist[j] < dist[t])) 
                t = j;
        st[t] = true;
        for (int j = 1; j <= n; ++j) dist[j] = min(dist[j], dist[t] + g[t][j]);
    }
    if (dist[n] == 0x3f3f3f3f) return -1; // 不存在最短路径
    return dist[n];
}
int main() {
    memset(g, 0x3f, sizeof g);
    cin >> n >> m;
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = min(g[a][b], c); // 防止重边的情况
    }
    cout << dijkstra() << '\n';
    return 0;
}

此代码时间复杂度为 \(O(n^2)\)。

优化

我们发现,朴素 \(Dijkstra\) 主要就耗时在找 \(t\) 上了;在一组数中找到一个最小值,我们自然可以想到用小根堆(不推荐手写)。

于是我们的代码就可以优化成这样了:

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define N 200000
typedef pair<int, int> PII; // 存储距离和节点编号
int n, m;
int h[N], e[N], w[N], ne[N], idx; // 因为是点数较多,所以用邻接表存图
int dist[N];
bool st[N];
void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; }
int dijkstra() {
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> q;
    q.push({0, 1});
    while (q.size()) {
        auto t = q.top();
        q.pop();
        int ver = t.second;
        if (st[ver]) continue;
        st[ver] = true;
        for (int i = h[ver]; i != -1; i = ne[i]) {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i]) {
                dist[j] = dist[ver] + w[i];
                q.push({dist[j], j});
            }
        }
    }
    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}
int main() {
    memset(h, -1, sizeof h);
    cin >> n >> m;
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
    }
    cout << dijkstra() << '\n';
    return 0;
}

剩下的咕咕,明天再写。

标签:ver,int,短路,st,算法,详解,短距离,dist,include
From: https://www.cnblogs.com/popfront/p/17659405.html

相关文章

  • zlmediakit源码学习(扩展支持算法分析)
    在zlmediakit源码基础上继续探索扩展支持算法分析功能。参照上一篇帖子:https://www.cnblogs.com/feixiang-energy/p/17623567.html算法模型使用opencv自带的人脸检测库:https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xmlzlme......
  • ChatGPT全称是什么?一文详解chatGPT含义、特点及未来发展
    一、引言近年来,人工智能(AI)技术的迅猛发展为人类生活带来了诸多变革。其中,聊天机器人(Chatbot)作为AI领域的重要应用之一,逐渐融入了我们的日常生活。而在这个领域中,ChatGPT成为了备受瞩目的明星产品。那么,ChatGPT全称是什么?它的含义又是怎样的呢?本文将详细解析ChatGPT的含义、特点以......
  • 垃圾收集器ParNew&CMS与底层三色标记算法详解
    垃圾收集算法分代收集理论当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。比如在新生代中,每次收集都会有大量对象(近9......
  • 跨境电商需要用到的电商API详解(淘宝京东拼多多1688API)
    随着电子商务的快速发展,跨境电商已经成为越来越多企业的选择。在跨境电商的业务流程中,电商API发挥着至关重要的作用。本文将详细介绍跨境电商需要用到的电商API,包括商品信息、商品类目信息、店铺信息、交易明细信息、商品管理、评价信息、店铺用户信息等。一、商品信息API  获......
  • 社团算法学习笔记
    社团算法学习笔记:https://gaowenxin95.github.io/le_graph/社团社区发现算法学习笔记.html......
  • 多元回归预测 | Matlab 粒子群算法优化随机森林(PSO-RF)回归预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 多元回归预测 | Matlab 鲸鱼算法优化随机森林(WOA-RF)回归预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 大厂算法每日总结(统计文件夹下的文件)
    //统计文件夹下的文件,是文件就累计1,隐藏文件空累计,文件不累计publicstaticvoidmain(String[]args){System.out.println(getFileNumber("D:\重要文件"));}publicstaticintgetFileNumber(StringfolderPath){Fileroot=newFile(folderPath);if(!root.isDirectory(......
  • 大厂算法题每日总结(num最近的,2的某次方)
    //给定一个非负整数num,不用循环,返回>=num,并离num最近的,2的某次方publicstaticfinalinttableSizeFor(intn){n--;n|=n>>>1;//>>>不带符号右移n|=n>>>2;n|=n>>>4;n|=n>>>8;n|=n>>>16;//打满,至此int32位,全打满return(n<0......
  • 大厂算法每日总结(GB字符串至少交换几次)
    //一个数组中只有两种字符'G'和'B',//想要所有的G都放左边,所有的B都放右边或者所有的B都放左边,所有的G都放右边//但只能在相邻字符之间进行交换操作//返回至少需要交换几次//方法1publicstaticintminSteps1(Strings){if(s==null||s.equals("")){return0;}......