【代码随想录训练营第42期 续Day58打卡 - 图论Part8 - Dijkstra算法

news2024/12/27 13:34:00

目录

一、Dijkstra算法

实现方式

1、使用优先队列(最小堆)

2、朴素法(简单数组) 

二、经典例题

题目:卡码网 47. 参加科学大会

题目链接

题解:朴素Dijkstra

 三、小结


一、Dijkstra算法

刚入门Dijkstra算法,可以看一下这个视频:最短路径查找—Dijkstra算法。

定义

Dijkstra算法是一种用于在带权图中找到从单一源点出发到所有其他顶点的最短路径的贪心算法

实现方式

Dijkstra算法主要有两种实现方式:使用优先队列(通常是最小堆)和朴素法(使用简单的数组)。

1、使用优先队列(最小堆)

伪代码:

DIJKSTRA(G, s)
    dist[s] <- 0
    prev[s] <- NULL
    for each vertex v in G.V - {s}
        dist[v] <- INFINITY
        prev[v] <- NULL
    Q <- priority queue containing all vertices in G.V with dist as key
    while Q is not empty
        u <- Q.extractMin()
        for each vertex v in G.Adj[u]
            if dist[u] + G.w(u, v) < dist[v]
                dist[v] <- dist[u] + G.w(u, v)
                prev[v] <- u
                Q.decreaseKey(v, dist[v])
    return dist[], prev[]
2、朴素法(简单数组) 

伪代码:

DIJKSTRA(G, s)
    dist[s] <- 0
    prev[s] <- NULL
    for each vertex v in G.V - {s}
        dist[v] <- INFINITY
        prev[v] <- NULL
    while there are unvisited vertices
        u <- vertex with min dist[u] among unvisited vertices
        mark u as visited
        for each vertex v in G.Adj[u]
            if dist[u] + G.w(u, v) < dist[v]
                dist[v] <- dist[u] + G.w(u, v)
                prev[v] <- u
    return dist[], prev[]

二、经典例题

题目:卡码网 47. 参加科学大会

题目链接

47. 参加科学大会(第六期模拟笔试) (kamacoder.com)

题目描述

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。

小明的起点是第一个车站,终点是最后一个车站。然而,途中的各个车站之间的道路状况、交通拥堵程度以及可能的自然因素(如天气变化)等不同,这些因素都会影响每条路径的通行时间。

小明希望能选择一条花费时间最少的路线,以确保他能够尽快到达目的地。

输入描述

第一行包含两个正整数,第一个正整数 N 表示一共有 N 个公共汽车站,第二个正整数 M 表示有 M 条公路。 

接下来为 M 行,每行包括三个整数,S、E 和 V,代表了从 S 车站可以单向直达 E 车站,并且需要花费 V 单位的时间。

输出描述

输出一个整数,代表小明从起点到终点所花费的最小时间。

输入示例

7 9
1 2 1
1 3 4
2 3 2
2 4 5
3 4 2
4 5 3
2 6 4
5 7 4
6 7 9

输出示例

12

提示信息

能够到达的情况:

如下图所示,起始车站为 1 号车站,终点车站为 7 号车站,绿色路线为最短的路线,路线总长度为 12,则输出 12。

不能到达的情况:

如下图所示,当从起始车站不能到达终点车站时,则输出 -1。

数据范围:

1 <= N <= 500;
1 <= M <= 5000;

题解:朴素Dijkstra

注意:Dijkstra算法适用于没有负权重边的有向图。如果图中存在负权重边,则应该使用Bellman-Ford算法。

本题思路如下:

初始化图:
    创建一个邻接矩阵grid,大小为n+1xn+1,所有值初始化为INT_MAX。
    创建一个数组minDist,大小为n+1,所有值初始化为INT_MAX,除了start顶点,其值为0。
    创建一个数组visited,大小为n+1,所有值初始化为false。

读取边信息:
    对于m次循环:
        读取p1, p2, val。
        在grid中设置grid[p1][p2] = val。

Dijkstra算法:
    初始化cur为-1,minVal为INT_MAX。
    对于i从1到n:
        找到未访问顶点中距离源点最近的顶点cur,更新minVal。
        如果cur为-1,退出循环。
        标记cur为已访问。
        对于v从1到n:
            如果v未被访问且grid[cur][v]不为INT_MAX:
                如果minDist[cur] + grid[cur][v] < minDist[v],则更新minDist[v]。

输出结果:
    如果minDist[end]为INT_MAX,则输出-1。
    否则,输出minDist[end]。

基于以上思路,完整实现代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n, m; // n为顶点数,m为边数
    cin >> n >> m;

    // 使用邻接矩阵表示图:顶点从1到n,初始化为无穷大(INT_MAX)
    vector<vector<int>> grid(n + 1, vector<int>(n + 1, INT_MAX));

    // 读取图的边信息
    for (int i = 0; i < m; i++)
    {
        int p1, p2, val;
        cin >> p1 >> p2 >> val;
        // 由于是有向图,只需要设置一个方向的权重
        grid[p1][p2] = val;
    }

    int start = 1; // 起始顶点
    int end = n;   // 终止顶点

    // 初始化最短距离数组,所有顶点到源点的距离都设置为无穷大(除了源点本身)
    vector<int> minDist(n + 1, INT_MAX);
    minDist[start] = 0; // 源点到自身的距离为0

    // 标记数组:标记顶点是否已访问 - 初始化为未访问
    vector<bool> visited(n + 1, false);

    // Dijkstra算法主循环,遍历所有顶点
    for (int i = 1; i <= n; i++)
    {
        int minVal = INT_MAX; // 初始化当前最小距离为无穷大
        int cur = -1;         // 初始化当前顶点为 -1

        // 找到未访问顶点中距离源点最近的顶点
        for (int v = 1; v <= n; ++v)
        {
            if (!visited[v] && minDist[v] < minVal)
            {
                minVal = minDist[v]; // 更新最小距离
                cur = v;             // 更新当前顶点
            }
        }
        if (cur == -1) // 如果没有找到这样的顶点,退出循环
            break;

        visited[cur] = true; // 标记该顶点已访问

        // 更新相邻顶点的最短距离
        for (int v = 1; v <= n; v++)
        {
            if (!visited[v] && grid[cur][v] != INT_MAX)
            {
                // 如果当前顶点到v顶点的距离加上当前顶点到源点的距离小于v顶点到源点的距离,则更新
                if (minDist[cur] + grid[cur][v] < minDist[v])
                    minDist[v] = minDist[cur] + grid[cur][v];
            }
        }
    }

    // 输出结果,如果到end顶点的距离仍然是无穷大,则说明无法到达
    if (minDist[end] == INT_MAX)
        cout << -1 << endl;
    else
        cout << minDist[end] << endl; // 输出最短路径长度
}

本题是针对有向图,故对于每条边只需要存储单方向的信息;如果是无向图,就需要改进为双向处理,即:

grid[p1][p2] = val;
grid[p2][p1] = val;

 三、小结

后边打卡会在此之后补充优化后的Dijkstra算法,即使用优先队列(最小堆)的方式。今天的打卡到此结束,后边会继续加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2138630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Git】常见命令(仅笔记)

文章目录 创建/初始化本地仓库添加本地仓库配置项提交文件查看仓库状态回退仓库查看日志分支删除文件暂存工作区代码远程仓库使用 .gitigore 文件让 git 不追踪一些文件标签 创建/初始化本地仓库 git init添加本地仓库配置项 git config -l #以列表形式显示配置项git config …

【免费】CISSP官方习题集第4版

伴随2004年4月CISSP新大纲发布&#xff0c;CISSP官方习题集第4版(OPT v4)已于2024年5月出版&#xff1a; 本人维护的中英对照8个知识域分章节练习已同步更新完成&#xff0c;在保持v3版内容基础上&#xff0c;增补了所有v4新内容&#xff0c;免费供考友们使用&#xff0c;访问方…

Requests-HTML模块怎样安装和使用?

要安装和使用Requests-HTML模块&#xff0c;您可以按照以下步骤进行操作&#xff1a; 打开命令行界面&#xff08;如Windows的命令提示符或Mac的终端&#xff09;。 使用pip命令安装Requests-HTML模块。在命令行中输入以下命令并按回车键执行&#xff1a; pip install request…

mp4文件解析

mp4格式与Annexb格式不同 实际送到GPU中解码数据是 00 00 01 + 编码数据,三个字节标识加解码数据 解析开始: for (uint32_t sampleIndex = 0; sampleIndex < track.sample_count; ++sampleIndex) {//----------------------------------------------------------…

28 线性表 · 栈

目录 一、概念与结构 &#xff08;一&#xff09;概念 1、栈 2、压栈 3、出栈 4、底层实现 二、栈的实现 三、栈的算法题 一、概念与结构 &#xff08;一&#xff09;概念 1、栈 一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除操作。进行数据插…

idea连接数据库大避雷!!!

再跟着黑马学习的时候&#xff0c;用黑马的资料安装的数据库&#xff0c;命令行能正常启动&#xff0c;SQLyog也能正常连接&#xff0c;就是tmd idea连接不了。不论是原始的jdbc,还是其它方式都不行&#xff0c;一直报错&#xff1a; 然后就各种搜&#xff0c;有的说数据库驱动…

【JavaEE初阶】多线程(4)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 线程安全的 第四个原因 代码举例: 分析原因 解决方法 方法1 方法2 wait(等待)和notify(通知) wait和sleep区别 线程安全的 第四个原因 内存可见性,引起的线程安全问…

AI辅助癌症诊断取得了进展

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

服务发现和代理实例的自动更新

1.服务发现的两种方式 StartFindService 方法 这是一个在后台启动的连续 “FindService” 活动&#xff0c;当服务实例的可用性发生变化时&#xff0c;会通过回调通知调用者。 它返回一个FindServiceHandle&#xff0c;可通过调用StopFindService来停止正在进行的监视服务实例…

pwn题目搭建过程中glibc出现问题的解决方案

前言&#xff1a; 在做pwn的堆题时&#xff0c;会遇到不同版本的glibc。为了更好地与远程环境对应&#xff0c;我们可以通过patchelf和glibc-all-in-one来更换程序动态加载时的glibc。简单介绍一下&#xff0c;glibc-all-in-one用来下载需要的glibc包&#xff0c;然后用petche…

【Git】初识Git

本篇文章的环境是在 Ubuntu/Linux 环境下编写的 文章目录 版本控制器Git 基本操作安装 Git创建 Git 本地仓库配置 Git认识工作区、暂存区、版本库添加文件修改文件版本回退撤销修改删除文件 版本控制器 在日常工作和学习中&#xff0c;老板/老师要求我们修改文档&#xff0c;…

Live800:客户服务新纪元,从响应到主动关怀的转型之路

在当今这个快速变化的商业环境中&#xff0c;客户服务已不再是简单的售后响应或问题解决的环节&#xff0c;而是企业赢得市场、构建品牌忠诚度、实现可持续增长的核心驱动力。随着技术的飞速发展和消费者需求的日益多样化&#xff0c;客户服务正步入一个新的纪元——从传统的被…

电脑上如何多开微信软件(多个微信同时使用)

想登录几个就下面这种文件里&#xff0c;复制几行即可&#xff1a; 创建的是以 .bat 文件结尾的txt文件&#xff08;先创建一个txt文本文档&#xff0c;等写好了命令保存后&#xff0c;再把文件的后缀名改为: .bat &#xff09;再保存即可。然后&#xff0c;右键以管理员运行&a…

电子废物检测回收系统源码分享

电子废物检测回收检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

mysql 8.0 日期维度表生成(可运行)

mysql 8.0 日期维度表生成&#xff08;可运行&#xff09; 文章目录 mysql 8.0 日期维度表生成&#xff08;可运行&#xff09;日期维度表左右日期维度表生成技术点 日期维度表左右 在数据仓库&#xff08;Data Warehouse&#xff09;中&#xff0c;日期维度表&#xff08;Dat…

离谱碾压!奇安信中标:高出第二名近70分!

2024年08月09日&#xff0c;广东省政务服务和数据管理局&#xff0c;近日发布了网络安全第三方服务&#xff08;2024年&#xff09;项目之关基检查及重要政务应用安全检查服务招标公告&#xff01; 预算金额&#xff1a;2,896,200.00元&#xff0c;其中安全检查服务包&#xf…

Pytorch+Anaconda+Pycharm+Python

0 python知识 0.1 os库常见用法 os 库提供了许多用于操作操作系统功能的函数。常见用法包括&#xff1a; 文件和目录操作&#xff1a; os.listdir(path)&#xff1a;列出指定路径下的所有文件和目录。os.mkdir(path)&#xff1a;创建新目录。os.remove(path)&#xff1a;删除…

清理C盘缓存,删除电脑缓存指令是什么

在处理计算机系统的C盘缓存清理任务时&#xff0c;需要谨慎操作以确保系统的稳定性和数据的安全性。通常&#xff0c;Windows操作系统中并没有直接的“一键清理C盘缓存”的单一命令&#xff0c;因为缓存文件分散存储于多个位置&#xff0c;并且有些缓存对于系统性能至关重要&am…

【MySQL】EXPLAIN(执行计划)关键字是什么?

简介&#xff1a; explain是一个强大的 SQL 命令&#xff0c;用于分析和优化查询性能。通过查看数据库执行计划&#xff0c;我们可以理解查询是如何被处理的&#xff0c;包括表的访问顺序、使用的索引、连接类型等。这对于找到潜在的性能瓶颈非常重要。 目录 一、基本含义 二…

四、链表————相关概念详解

链表 前言一、链表是什么&#xff1f;二、链表的类型2.1 单向链表2.2 环形链表2.3 双向链表 三、链表中常用操作 (以单向列表为例)3.1 初始化链表3.2 判断链表是否为空3.3 获取链表长度3.4 插入节点3.4.1 链表头部添加节点3.4.2 链表尾部添加节点3.4.3 指定位置添加节点 3.5 删…