关于几种求最短路算法的碎碎念(Dijkstra、spfa、floyd)

news2025/7/21 18:42:32

目录

一、求1号点到n号点的最短路

1、所有边都是正数——Dijkstra

(1)朴素版dijkstra - 邻接矩阵

(2)堆优化版dijstra - 邻接表

2、存在负权边——spfa

3、dijkstra和spfa的区别

二、起点和终点未知,求某两点间最短路 —— Floyd


一、求1号点到n号点的最短路

1、所有边都是正数——Dijkstra

【蓝桥杯集训14】Dijkstra求最短路(3 / 3)_Roye_ack的博客-CSDN博客

(1)朴素版dijkstra - 邻接矩阵

初始化准备:

dist[i]=从1~i点最短距离   初始化dist[i]=0x3f3f3f3f   dist[1]=0

n次循环

{

        1、从1~n点中找到未标记的点中,离起点最近的点

        2、标记该点

        3、用该点更新到其他点的最小距离

}

    public static int dijkstra()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        
        for(int i=0;i<n;i++) //n次循环
        {
            int t=-1;
            //先找出未标记的点中 距离起点最近的点
            for(int j=1;j<=n;j++)
                if(st[j]==0&&(t==-1||dist[j]<dist[t])) 
                    t=j;
            
            st[t]=1;
            
            //用t更新到其他点的最短距离
            for(int j=1;j<=n;j++) dist[j]=Math.min(dist[j],dist[t]+g[t][j]);
        }
        
        return dist[n];
    }

(2)堆优化版dijstra - 邻接表

初始化准备:

dist[i]=从1~i点最短距离   初始化dist[i]=0x3f3f3f3f   dist[1]=0

  • 点1先入队,小顶堆q.offer({距离,点}) //按距离排序
  • 小顶堆的作用就是优化在1~n中找离起点最近的点
  • 标记该点
  • 用该点更新到其他点的最小距离,没标记的入队
public static int dijkstra()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        PriorityQueue<PII> q=new PriorityQueue<>();
        q.offer(new PII(0,1)); //按first排序 所以距离放前边
        
        while(!q.isEmpty())
        {
            var t=q.poll();
            int p=t.y;
            int d=t.x;
            
            if(st[p]==1) continue;
            st[p]=1;
            
            for(int i=h[p];i!=-1;i=ne[i])
            {
                int j=e[i];
                if(dist[j]>d+w[i]) 
                {
                    dist[j]=d+w[i];
                    q.offer(new PII(dist[j],j));
                }
            }
        }
        
        return dist[n];
    }

 

2、存在负权边——spfa

【蓝桥杯集训15】求最短路存在负权边——spaf算法(3 / 3)_Roye_ack的博客-CSDN博客

初始化准备:

dist[i]=从1~i点最短距离   初始化dist[i]=0x3f3f3f3f   dist[1]=0 

st[x]数组标记x节点是否在队列中

  • 建立队列,队列初始只有节点1,标记节点1
  • 取出队头节点x,取消该点标记,遍历x所有出边(x,y,z),若dist[y]>dist[x]+w,则更新最短路dist[y]=dist[x]+w,若y不在队列中,让y入队并标记
  • 重复上述步骤,直到队列为空

求负环一般使用spfa算法,方法是用一个cnt数组记录每个点到源点的边数,一个点被更新一次就+1,一旦有点的边数达到了n那就证明存在了负环

    public static int spaf()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        st[1]=1;
        Queue<Integer> q=new LinkedList<>();
        q.offer(1);
        
        while(!q.isEmpty())
        {
            var t=q.poll();
            st[t]=0;
            
            for(int i=h[t];i!=-1;i=ne[i])
            {
                int j=e[i];
                if(dist[j]>dist[t]+w[i])
                {
                    dist[j]=dist[t]+w[i];
                    if(st[j]==0) //如果当前队列里不存在该节点 则入队并标记
                    {
                        q.offer(j);
                        st[j]=1;
                    }
                }
            }
        }
        return dist[n];
    }

 

3、dijkstra和spfa的区别

  • dijstra是局部最优的思想,也就是前面节点确定最短路后不会再更新,是拿已经最短的节点去更新它的后继节点,所以并不能及时更新每个节点的最小值

  • spfa通过队列实现,出队就去掉标记,入队就打上标记,如果某点前驱节点更新,后继一定会跟着更新,也就是队列循环更新 直至队空,因此可以及时更新每个节点最小值

 

二、起点和终点未知,求某两点间最短路 —— Floyd

【蓝桥杯集训16】多源汇求最短路——Floyd算法(2 / 2)_Roye_ack的博客-CSDN博客

这个原理来自于动态规划,背板子就行 

public static void floyd()
    {
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    d[i][j]=Math.min(d[i][j],d[i][k]+d[k][j]);
    }

 

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

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

相关文章

【16】linux命令每日分享——chmod修改权限

大家好&#xff0c;这里是sdust-vrlab&#xff0c;Linux是一种免费使用和自由传播的类UNIX操作系统&#xff0c;Linux的基本思想有两点&#xff1a;一切都是文件&#xff1b;每个文件都有确定的用途&#xff1b;linux涉及到IT行业的方方面面&#xff0c;在我们日常的学习中&…

使用QIS(Quantum Image Sensor)图像重建总结(1)

最近看了不少使用QIS重建图像的文章&#xff0c;觉得比较完整详细的还是Abhiram Gnanasambandam的博士论文&#xff1a;https://hammer.purdue.edu/articles/thesis/Computer_vision_at_low_light/20057081 1 介绍 讲述了又墨子的小孔成像原理&#xff0c;到交卷相机&#xf…

[AI助力] 2022.3.3 考研英语学习 2012 英语二翻译

[AI助力] 2022.3.3 考研英语学习 2012 英语二翻译 文章目录[AI助力] 2022.3.3 考研英语学习 2012 英语二翻译2012年英语二翻译真题总结积累&#x1f9d0;来点好玩的想法~ 这次试试让AI做更多的事情它居然给出了流汗黄豆&#x1f605;让它评价一下参考答案让AI评价我的翻译让AI …

工具及方法 - Windows下出现“IPv4/IPv6 No Internet Access“错误

家里的PS4&#xff0c;突然用电信网刷新不了PS会员游戏了。同样的网&#xff0c;登录微软账号也登不上。难道是网络问题&#xff1f; 可我换成手机热点就是好的&#xff0c;而且PS4再用电信网络就恢复了。 让我郁闷了一下&#xff0c;开始怀疑人生。后来上网查了一下&#xf…

IM即时通讯开发用Netty实现心跳机制、断线重连机制

所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性。注&#xff1a;心跳包还有另一个作用&#xff0c;经常被忽略&#xff0c;即&#xff1a;一个连接如果长时间不用&#xff0c;防火墙或者路由器就会…

百天百题(1/100)Java创建线程的方式?

首先创建线程有四种种方式&#xff1a; 1.继承Thread类 缺点&#xff1a;1.Java是不支持多继承的&#xff0c;所以我们不能在继承其他的类了 2.不能通过线程池来此操作&#xff0c;每次创建一个线程都需要先创建一个类&#xff0c;创建和销毁线程对整体的资源开销是非常大的。…

Thread 类的基本用法

1.线程创建 Thread类&#xff1a;创建的线程都是一样的 1.继承Thread,重写run&#xff1b; 2.实现Runable,重写run&#xff1b; 3.使用匿名内部类&#xff0c;继承Thread; 4.使用匿名内部类&#xff0c;实现Runnable&#xff1b; 5.使用lambda表达式&#xff08;常用&#xff…

IDEA插件系列(3):Maven Helper插件

一、引言在写Java代码的时候&#xff0c;我们可能会出现Jar包的冲突的问题&#xff0c;这时候就需要我们去解决依赖冲突了&#xff0c;而解决依赖冲突就需要先找到是那些依赖发生了冲突&#xff0c;当项目比较小的时候&#xff0c;还比较依靠IEDA的【Diagrams】查看依赖关系&am…

嵌入式学习笔记——使用寄存器编程操作GPIO

使用寄存器编程操作GPIO前言GPIO相关的寄存器GPIO 端口模式寄存器 (GPIOx_MODER) (x A..I)位操作GPIO 端口输出类型寄存器 (GPIOx_OTYPER) (x A..I)GPIO 端口输出速度寄存器 (GPIOx_OSPEEDR) (x A..I/)GPIO 端口上拉/下拉寄存器 (GPIOx_PUPDR) (x A..I/)GPIO 端口输入数据寄…

Python bool 到底怎么用? 【源码拆解】

人生苦短 我用python 一、布尔类型描述 布尔类型是计算机中最基本的类型&#xff0c; 它是计算机二进制世界的体现&#xff0c;一切都是 0 和 1 。 Python中的布尔类型只有两种值&#xff1a;True 和 False 。 &#xff08;注意&#xff1a;首字母都是大写&#xff0c;与C、Ja…

女生学习大数据怎么样~有前景么

当前大数据发展前景非常不错&#xff0c;且大数据领域对于人才类型的需求比较多元化&#xff0c;女生学习大数据也会有比较多的工作机会。大数据是一个交叉学科涉及到的知识量比较大学习有一定的难度&#xff0c;女生则有女生的优势&#xff0c;只要认真学习了都是可以做大数据…

STM32定时器的编码器接口模式

MCU为STM32L431&#xff0c;通用定时器框图&#xff1a; 编码器接口模式一共有三种&#xff0c;通过TIMx_SMCR寄存器的SMS[3:0]位来选择。模式1计数器仅在TI1FP1的边沿根据TI2FP2的电平来判断向上/下计数&#xff1b;模式2计数器仅在TI2FP2的边沿根据TI1FP1的电平来判断向上/下…

Python面向对象的三大特征 - - 封装、继承、多态

目录 一、三大特征介绍 1、封装&#xff08;隐藏&#xff09; 2、继承 3、多态 二、继承 1、子类扩展父类 1.语法格式 2.构造函数 2、类成员的继承和重写 1. 成员继承 2. 方法重写 3、查看类的继承层次结构 4、object根类 1.描述 2. dir() 查看对象属性&#xff…

JVM-可达性分析算法

JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈…

maven的学习

为啥要用maven 1、不用认为添加jar包所依赖的其他jar包 2、能在本地仓库只保留一份jar包&#xff0c;避免了多个工程使用相同jar包&#xff0c;需要重复导入的问题&#xff0c;减少冗余 3、能够规范添加jar包&#xff0c;在下载需要的jar包时有多种方法&#xff0c;但是不能保…

TeeChart VCL/FMX v2023 crack

TeeChart VCL/FMX v2023 crack TeeChart Pro VCL允许您为所有领域(包括商业、工程、金融、统计、科学、医疗、实时和网络)创建通用和专用图表和绘图应用程序。TeeChart Pro VCL具有多种图表类型的图表库&#xff0c;包括2D或3D线条、条形图、水平条、区域、点、饼图、箭头、气泡…

MySQL OCP888题解043-GTID模式下如何解决主键冲突问题

文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析3、知识点3.1、知识点1&#xff1a;GTID模式下跳过一个事务的方法4、总结1、原题 1.1、英文原题 A simple master-to-slave replication is currently being used. This information is extracted from the SH…

Kubernetes学习(三)Service

Service对象 为什么需要Service 每个Pod都有自己的IP地址&#xff0c;但是在Deployment中&#xff0c;在同一时刻运行的Pod集合可能与稍后运行该应用程序的Pod集合不同。 这就导致了一个问题&#xff1a;如果一组Pod&#xff08;称为后端&#xff09;为集群内其他Pod&#x…

Java测试题

选择题&#xff08;共15题&#xff0c;每题2分&#xff09;( B ) 1、使用下面哪个表达式能产生[20,999]之间的数&#xff1f;A.(int)(20Math.random( )*979) B.20(int)(Math.random( )*980)C.(int)Math.random( )*999 D.20(int)Math.random( )*980( C )2、请仔细阅读下面的程序…

【记录】Samba|Windows 11的Samba连接切换用户

Samba是一个用于共享文件和打印机的网络协议&#xff0c;可以使不同的操作系统之间共享文件和资源变得容易。在Windows 11上&#xff0c;可以使用Samba来连接到网络共享。 如果您想在Windows 11上切换用户并连接到另一个Samba共享&#xff0c;可以按照以下步骤操作。 文章目录…