图论 之 迪斯科特拉算法求解最短路径

文章目录

  • 题目
    • 743.网络延迟时间
    • 3341.到达最后一个房间的最少时间I

求解最短路径的问题,分为使用BFS和使用迪斯科特拉算法,这两种算法求解的范围是有区别的

  • BFS适合求解,边的权值都是1的图中的最短路径的问题
    图论 之 BFS
  • 迪斯科特拉算法适合求解边的权值不一样的图,其中,该算法有两种实现方式,分别适用于两种情况的图
    • 稠密图,使用朴素的Dijkstra算法,其中稠密图的定义是,边的数量级与 o ( n 2 ) o(n^2) o(n2)相当的图,朴素的Dijkstra算法的时间复杂度是 o ( n 2 ) o(n^2) o(n2),其中n是图的节点的数量
    • 稀疏图,使用堆优化的Dijkstra算法,算法的时间复杂度是 o ( m l o g m ) o(mlogm) o(mlogm)其中,m是边的数量,如果输入的稠密图,那么使用堆优化的Dijkstra算法的时间复杂度是 o ( n 2 l o g n ) o(n^2logn) o(n2logn)

朴素的Dijkstras算法的模版

# 存储边的情况
edge = [[float('inf')]*n for n in range(n)]
# dis[i]表示 单源点k到其余节点i的最短的路径
dis = [float('inf')]*n 
dis[k] = 0
# 这个done[k] = True不用设置,后面会依据这个,把起点弹出
done = [False]*n # done[i]标记是否找到 到达节点i的最短的路径

while True:
	x = -1
	for i,ok in enumerate(done):
		# 找到在还没确定最小距离的节点,该节点到源点的距离最小
		if not ok and (x < 0 or dis[i] < dis[x]):
			x = i
	# 判断是否都找到了
	if x < 0:
		# 这里就已经求解完成了,后续你可以返回最大值?
		return dis
	# 有节点无法到达
	if dis[x] == float('inf'):
		return -1
	# 设置标志位,表示节点x的最小距离已经确定
	done[x] = True
	# 遍历当前节点的所有的邻居,更新答案
	for j,d in enumerate(edge[x]):
		dis[j] = min(dis[j],dis[j]+d)
		

使用堆优化的Dijkstra算法


import heapq

class Solution:
    def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
        # 使用堆优化的Dijkstra算法
        # 使用堆优化的话,适用于稀疏图,所以边的记录,我们使用邻接表
        edge = [[] for _ in range(n)]
        for x,y,z in times:
            edge[x-1].append((y-1,z))
        
        dis = [float('inf')]*n 
        dis[k-1] = 0
        # 入堆的元素是 (dis[x],x),第一个元素是距离,这也是设置的优先级
        h = [(0,k-1)]
        while h:
        	# 出堆
            dx,x = heapq.heappop(h)
            # 如果当前的距离大于最小距离,直接过
            if dx > dis[x]:
                # 说明之前出过堆
                continue
            # 访问邻居,不一定是这个邻接表或者邻接矩阵,二维表也可以
            for y,d in edge[x]:
            	# 计算更新值,计算方式按照题目的意思
                new_dis = dx + d 
                # 只有更优的值才能被加入进去
                if new_dis < dis[y]:
                    dis[y] = new_dis
                    heapq.heappush(h,(new_dis,y))
        mx = max(dis)
        return mx if mx < float('inf') else -1

题目

743.网络延迟时间

743.网络延迟时间

在这里插入图片描述

在这里插入图片描述

思路分析:由于边的数量远远大于节点的数量,所以我们还是考虑使用稠密图下的朴素的Dijkstra算法,最后返回不是无穷的最大的路径即可

class Solution:
    def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
        # 区别于BFS求解的最短距离,这个距离的边的权值不一样
        # 使用朴素的迪斯科特拉算法

        # 邻接矩阵记录边的情况
        edge = [[float('inf')]*(n) for _ in range(n)]
        # 有向边
        for e in times:
            edge[e[0]-1][e[1]-1] = e[2]
        
        dis = [float('inf')]*n # 记录k到各个节点的最短距离
        ans = dis[k-1] = 0
        done = [False] * n # 记录节点的最短距离是否被确定
        while True:
            x = -1
            # 找到最短距离还没确定,并且节点k到它的距离是最短的节点
            for i,ok in enumerate(done):
                if not ok and (x<0 or dis[i] < dis[x]):
                    x = i 
            # 如果x<0,表示全部的节点已经全部都访问过了
            if x < 0 :
                return ans
            # 如果最短的节点的距离是无穷,说明不可达
            if dis[x] == float('inf'):
                return -1
            # 更新
            ans = dis[x]
            done[x] = True
            for y,d in enumerate(edge[x]):
                dis[y] = min(dis[y],dis[x]+d)

使用堆优化的解法

import heapq

class Solution:
    def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
        # 使用堆优化的Dijkstra算法
        # 使用堆优化的话,适用于稀疏图,所以边的记录,我们使用邻接表
        edge = [[] for _ in range(n)]
        for x,y,z in times:
            edge[x-1].append((y-1,z))
        
        dis = [float('inf')]*n 
        dis[k-1] = 0
        # 入堆的元素是 (dis[x],x)
        h = [(0,k-1)]
        while h:
            dx,x = heapq.heappop(h)

            if dx > dis[x]:
                # 说明之前出过堆
                continue
            for y,d in edge[x]:
                new_dis = dx + d 
                if new_dis < dis[y]:
                    dis[y] = new_dis
                    heapq.heappush(h,(new_dis,y))
        mx = max(dis)
        return mx if mx < float('inf') else -1

3341.到达最后一个房间的最少时间I

3341.到达最后一个房间的最少时间I

在这里插入图片描述

思路分析:开始的时候,我错误的以为题目中只能向右或者向下运动, 所以写了一个动态规划进行求解,实际上,这个思路是错误的,不过要是只能向下或者向右运动的话,动态规划也是一种很好的做法

# 动态规划的做法,竟然可以过700个测试用例
import heapq
class Solution:
    def minTimeToReach(self, moveTime: List[List[int]]) -> int:
        # 开始的时候从(0,0)出发,移动到相邻的房间,其实也只是向下或向右运动
        # 感觉可以用动态规划,dp[i][j]表示到达i,j所需的最少的时间
        # 递推公式,
        # dp[i][j] = min(max(dp[i-1][j],moveTime[i][j])+1,max(dp[i][j-1],moveTime[i][j])+1)
        n = len(moveTime)
        m = len(moveTime[0])
        dp = [[float('inf')]*(m+1) for _ in range(n+1)]
        dp[1][1] = 0
        for i in range(n):
            for j in range(m):
                if i == 0 and j == 0:
                    continue
                dp[i+1][j+1] = min(max(dp[i][j+1],moveTime[i][j])+1,max(dp[i+1][j],moveTime[i][j])+1)
        for i in dp:
            print(i )

        return dp[n][m]

正确的思路:应该是使用Dijkstra算法,不过开始的时候,我有点纠结这个edge也就是边的矩阵如何转化为邻接矩阵或者邻接表,后面一想,还是我的固定思维阻碍了我,邻接矩阵和邻接表只是一个工具,帮助我们找到当前的节点的邻居,但是在现在的图中,你通过坐标的加减不就可以得到对应的邻居嘛!

  • 展示使用朴素Dijkstra算法做法
import heapq
class Solution:
    def minTimeToReach(self, moveTime: List[List[int]]) -> int:
        # 首先先使用 堆优化的Dijkstra进行解题
        # 图已经构建,就是moveTime
        # dis[i][j]表示(0,0)到(i,j)的最短的时间
        n,m = len(moveTime),len(moveTime[0])
        dis = [[float('inf')]*m for _ in range(n)]
        dis[0][0] = 0
        done = [[False]*m for _ in range(n)]
        while True:
            x,y = -1,-1
            # 开始遍历还没确定的点
            for i in range(n):
                for j in range(m):
                    if not done[i][j] and ((x<0 and y <0) or dis[i][j] < dis[x][y]):
                        x,y = i,j
            if x<0 and y <0:
                # 说明都找到了
                return dis[n-1][m-1]
            
            # 设置已经找到
            done[x][y] = True
            # 访问邻居
            for i,j in (x+1,y),(x-1,y),(x,y+1),(x,y-1):
                if 0<= i < n and 0<= j < m:
                    dis[i][j] = min(max(dis[x][y],moveTime[i][j]) + 1,dis[i][j])


  • 展示使用堆优化的Dijkstra算法
import heapq
class Solution:
    def minTimeToReach(self, moveTime: List[List[int]]) -> int:
        # 首先先使用 堆优化的Dijkstra进行解题
        # 图已经构建,就是moveTime
        # dis[i][j]表示(0,0)到(i,j)的最短的时间
        n,m = len(moveTime),len(moveTime[0])
        dis = [[float('inf')]*m for _ in range(n)]
        dis[0][0] = 0
        h = [(0,0,0)]

        while True:
            d,x,y = heapq.heappop(h)
            if x == n-1 and y == m-1:
                return d 
            # 已经更新过了
            if d > dis[x][y]:
                continue
            
            # 访问邻居:
            for i,j in (x+1,y),(x-1,y),(x,y+1),(x,y-1):
                if 0<= i <n and 0<= j < m:
                    # 合法的坐标
                    # 计算当前的距离,小于才入堆
                    new_dis = max(d,moveTime[i][j])+1
                    if dis[i][j]>new_dis:
                        dis[i][j] = new_dis
                        heapq.heappush(h,(dis[i][j],i,j))

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在mfc中使用自定义三维向量类和计算多个三维向量的平均值

先添加一个普通类, Vector3.h, // Vector3.h: interface for the Vector3 class. // //#if !defined(AFX_VECTOR3_H__53D34D26_95FF_4377_BD54_57F4271918A4__INCLUDED_) #define AFX_VECTOR3_H__53D34D26_95FF_4377_BD54_57F4271918A4__INCLUDED_#if _MSC_VER > 1000 #p…

DM执行计划

DM执行计划 1. 引言 理解执行计划对于优化查询性能、诊断慢查询问题至关重要。本文将从基础概念入手&#xff0c;逐步深入探讨执行计划的各个组成部分&#xff0c;并通过设计用例来验证所学知识。 2. SQL 执行计划基础 SQL 执行计划是数据库引擎在执行 SQL 语句时生成的一个…

【鸿蒙开发】第四十三章 Notification Kit(用户通知服务)

目录​​​​​​​ 1 简介 1.1 使用场景 1.2 能力范围 1.3 业务流程 1.4 通知样式 1.5 约束限制 1.6 与相关Kit的关系 2 请求通知授权 2.1 接口说明 2.2 开发步骤 3 管理通知角标 3.1 接口说明 3.2 开发步骤 4 管理通知渠道 4.1 通知渠道类型说明 4.2 接口说明…

SpringBoot:SSL证书部署+SpringBoot实现HTTPS安全访问

一、前言 SSL协议介于TCP/IP协议栈的第四层&#xff08;传输层&#xff09;和第七层&#xff08;应用层&#xff09;之间&#xff0c;为基于TCP的应用层协议&#xff08;如HTTP&#xff09;提供安全连接。它通过在客户端和服务器之间建立一个加密的通道&#xff0c;确保数据在传…

【数学】数论干货(疑似密码学基础)

文章目录 前言一. 整除、算术基本定理、同余、同余类、剩余系的基本定义1.整除2.算数基本定理3.同余4.同余类&#xff08;也叫剩余类&#xff09;5.剩余系 二. 费马小定理的内容及其证明1.费马小定理基本内容2.费马小定理的证明&#xff08;interesting 版&#xff09; 三. 欧拉…

[实现Rpc] 消息抽象层的具体实现

目录 具象层 _ 消息抽象的实现 信息的抽象类 实现 JsonMessage JsonRequest & JsonResponse 消息-不同消息分装实现 实现 Request RpcRequest TopicRequest ServiceRequest Response RpcResponse TopicResponse ServiceResponse 实现 生产工厂 本篇文章继 …

《A++ 敏捷开发》- 16 评审与结对编程

客户&#xff1a;我们的客户以银行为主&#xff0c;他们很注重质量&#xff0c;所以一直很注重评审。他们对需求评审、代码走查等也很赞同&#xff0c;也能找到缺陷&#xff0c;对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。 我&#xff1a;你听说过敏捷的结对…

PHP房屋出租出售高效预约系统小程序源码

&#x1f3e0; 房屋出租出售高效预约系统 —— 您的智能找房新选择 &#x1f4a1; 这是一款集智慧与匠心于一体的房屋出租出售预约系统&#xff0c;它巧妙地融合了ThinkPHP与Uniapp两大先进框架&#xff0c;精心打造而成。无论是小程序、H5网页&#xff0c;还是APP端&#xff…

给老系统做个安全检查——Burp SqlMap扫描注入漏洞

背景 在AI技术突飞猛进的今天&#xff0c;类似Cursor之类的工具已经能写出堪比大部分程序员水平的代码了。然而&#xff0c;在我们的代码世界里&#xff0c;仍然有不少"老骥伏枥"的系统在兢兢业业地发光发热。这些祖传系统的代码可能早已过时&#xff0c;架构可能岌…

Repeated Sequence

记suma[1]a[2]a[3]...a[n]。 该序列以a[1]&#xff0c;a[2]&#xff0c;a[3]....a[n]为循环节&#xff0c;明显的&#xff0c;问题可转化为:s%sum是否为该序列的某个连续子序列和。 断环为链。将a复制一份。 枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O&#x…

【DeepSeek】Mac m1电脑部署DeepSeek

一、电脑配置 个人电脑配置 二、安装ollama 简介&#xff1a;Ollama 是一个强大的开源框架&#xff0c;是一个为本地运行大型语言模型而设计的工具&#xff0c;它帮助用户快速在本地运行大模型&#xff0c;通过简单的安装指令&#xff0c;可以让用户执行一条命令就在本地运…

dockerfile 使用环境变量

ARG&#xff1a; Defining build-time variables ARG指令允许您定义在构建阶段可以访问但在构建映像之后不可用的变量。例如&#xff0c;我们将使用这个Dockerfile来构建一个映像&#xff0c;我们在构建过程中使用ARG指令指定的变量。 FROM ubuntu:latest ARG THEARG"fo…

基于WebGIS技术的校园地图导航系统架构与核心功能设计

本文专为IT技术人员、地理信息系统&#xff08;GIS&#xff09;开发者、智慧校园解决方案架构师及相关领域的专业人士撰写。本文提出了一套基于WebGIS技术的校园地图导航系统构建与优化方案&#xff0c;旨在为用户提供高效、智能、个性化的导航体验。如需获取校园地图导航系统技…

idea连接gitee(使用idea远程兼容gitee)

文章目录 先登录你的gitee拿到你的邮箱找到idea的设置选择密码方式登录填写你的邮箱和密码登录成功 先登录你的gitee拿到你的邮箱 具体位置在gitee–>设置–>邮箱管理 找到idea的设置 选择密码方式登录 填写你的邮箱和密码 登录成功

【从0做项目】Java音缘心动(3)———加密算法 MD5 BCrypt

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 零&#xff1a;项目结果展示 一&#xff1a;音乐播放器Web网页介绍 二&#xff1a;加密算法介绍 1&…

新数据结构(12)——代理

什么是代理 在进行操作时有时不希望用户直接接触到目标&#xff0c;这时需要使用代理让用户间接接触到目标 给目标对象提供一个代理对象&#xff0c;并且由代理对象控制着对目标对象的引用 图解&#xff1a; 代理的目的 控制访问&#xff1a;通过代理对象的方式间接的访问目…

基于大语言模型的推荐系统(1)

推荐系统&#xff08;recommendation system&#xff09;非常重要。事实上&#xff0c;搜索引擎&#xff0c;电子商务&#xff0c;视频&#xff0c;音乐平台&#xff0c;社交网络等等&#xff0c;几乎所有互联网应用的核心就是向用户推荐内容&#xff0c;商品&#xff0c;电影&…

学习threejs,使用MeshBasicMaterial基本网格材质

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshBasicMaterial 二…

Selenium实战案例2:东方财富网股吧评论爬取

上一篇文章&#xff0c;我们使用Selenium完成了网页内文件的自动下载,本文我们将使用Selenium来爬取东方财富网股吧内笔记的评论数据。 网页内容分析 网页内容的分析是web自动化中的关键一步。通过分析网页结构&#xff0c;我们可以确定需要抓取的数据位置以及操作元素的方式。…

零基础学python--------第三节:Python的流程控制语法

Python&#xff0c;浮点数 11.345(单&#xff1a;4个字节&#xff0c; 双&#xff1a;8个字节) 。 十进制的数字25 ---> 11001 讲一个小数转化为二进制&#xff1a; 不断的乘以2 。取整数部分。 十进制的0.625 ----> 二进制&#xff1a; 0&#xff0c; 101 。 0.3 ---…