Dijkstra算法的入门与应用

news2024/11/17 11:50:01

目录

一、前言

二、Dijkstra算法

1、Dijkstra 算法简介

2、算法思想:多米诺骨牌

3、算法实现

4、例子

三、例题

1、蓝桥王国(lanqiaoOJ题号1122)


一、前言

本文主要讲了Dijkstra算法的概念、实现与一道模板例题。

二、Dijkstra算法

1、Dijkstra 算法简介

  • Dijkstra:单源最短路径问题。
  • 优点:非常高效而且稳定。
  • 缺点:图的边权不能为负值。
  • 思路:贪心思想+优先队列+BFS。

2、算法思想:多米诺骨牌

  • 在图中所有的边上,排满多米诺骨牌。
  • 一条边上的多米诺骨牌数量,等于边的权值。
  • 规定所有骨牌倒下的速度都一样。在一个结点上推倒骨牌,会导致这个结点上的所有骨牌都往后面倒下去。
  • 在起点 s 推倒骨牌,从 s 开始,它连接的边上的骨牌都逐渐倒下,并到达所有能达到的结点。
  • 在某个结点 t,可能先后从不同的线路倒骨牌过来。

  • 先倒过来的骨牌,其经过的路径,肯定就是从 s 到达 t 的最短路;
  • 后倒过来的骨牌,对确定结点 t 的最短路没有贡献,不管它。
  • 在 s 的所有直连邻居中,最近的邻居 u,骨牌首先到达。u 是第一个确定最短路径的结点。从u 直连到 s 的路径肯定是最短的,因为如果 u 绕道别的结点到 s,必然更远。
  • 然后,把后面骨牌的倒下分成 2 部分,一部分是从 s 继续倒下到 s 的其它的直连邻居,另一部分从 u 出发倒下到 u 的直连邻居。下一个到达的结点 v,必然是 s 或者 u 的一个直连邻居。v 是第二个确定最短路径的结点。
  • 继续以上步骤,在每一次迭代过程中,都能确定一个结点的最短路径。

【特点】

  • Dijkstra 算法应用了贪心法的思想,即 “抄近路走,肯定能找到最短路径”。
  • 算法高效稳定:
  • >Dijkstra的每次迭代,只需要检查上次己经确定最短路径的那些结点的邻居,检查范围很小,算法是高效的;
  • >每次迭代,都能得到至少一个结点的最短路径,算法是稳定的。

3、算法实现

【维护两个集合】

己确定最短路径的结点集合 A、这些结点向外扩散的邻居结点集合B。

1)把起点 s 放到 A 中,把 s 所有的邻居放到 B 中。此时,邻居到 s 的距离就是直连距离。
2)从 B 中找出距离起点 s 最短的结点 u,放到 A 中。

3)把 u 所有的新邻居放到 B 中。显然,u 的每一条边都连接了一个邻居,每个新邻居都要加进去。其中 u 的一个新邻居 v,更新它到 s 的距离 dis(s,w),等于 dis(s,w) 和 dis(s,u)+dis(u,w) 的最小值。
4)重复(2)、(3),直到 B 为空时,结束。

【优先队列】

  • 每次往 B 中放新数据时,按从小到大的顺序放,用二分法的思路,复杂度是 O(logn),保证最小的数总在最前面:
  • 找最小值,直接取 B 的第一个数,复杂度是 O(1)。
  • 复杂度:用优先队列时,Dijkstra 算法的复杂度是 O(mlogn),是最高效的最短路算法。

【边权不能为负】

  • Dijkstra 的局限性是边的权值不能为负数
  • Dijkstra 基于 BFS,计算过程是从起点 s 逐步往外扩散的过程,每扩散一次就用贪心得到到一个点的最短路。
  • 扩散要求路径越来越长,如果遇到一个负权边,会导致路径变短,使扩散失效。
  • 设当前得到 s->u 的最短路,路径长度为 8,此时 s->u 的路径计算己经结束。
  • 继续扩展 u 的邻居,若 u 到邻居 v 的边权是 -15,而 v 到 s 的距离为 20,那么 u 存在另一条途径 v 到 s 的路径,距离为 20+(-15)=5,这推翻了前面己经得到的长度 8 的最短路,破坏了 BFS 的扩散过程。

4、例子

起点是 1,求 1 到其它所有结点的最短路径。

1)1 到自己的距离最短,把 1 放到集合A里:A=11。把 1 的邻居放到集合 B 里:B={ (2-5),(3-2)}。其中(2-5)表示结点 2 到起点的距离是 5。

2)从 B 中找到离集合 A 最近的结点,是结点 3。在 A 中加上 3,现在 A={1,31},也就是说得到了从 1 到 3 的最短距离;从 B 中拿走 (3-2),现在 B={(2-5)} 

3)对结点 3 的每条边,扩展它的新邻居,放到 B 中。3 的新邻居是 2 和 4,那么 B={(2-5),(2-4),(4,7)}。其中 (2-4) 是指新邻居 2 通过 3 到起点 1,距离是 4。由于 (2-4) 比 (2-5) 更好,丢弃 (2-5),B={ (2-4),(4-7) }。

4)重复步骤(2)、(3)。从 B 中找到离起点最近的结点,是结点 2。在 A 中加上 2,并从 B 中拿走 (2-4);扩展 2 的邻居放到 B 中。现在 A={1,3,2},B={(4-7),(4-5)}。由于 (4-5) 比 (4-7) 更好,丟弃 (4-7),B={(4-5)}。

5)从 B 中找到离起点最近的结点,是结点 4。在 A 中加上 4, 并从 B 中拿走 (4-5)。已经没有新邻居可以扩展。现在 A=(1,3,2,4},B 为空,结束。

三、例题

1、蓝桥王国(lanqiaoOJ题号1122)

【题目描述】

蓝桥王国一共有 N 个建筑和 M 条单向道路,每条道路都连按着两个建筑,每个建筑都有自己编号,分别为 1~N。(其中皇宫的编号为1)

国王想让小明回答从 皇宫到每个建筑的最短路径是多少,但紧张的小明此时己经无法思考,请你编写程序帮助小明回答国王的考核。

【输入描达】

输入第一行包含 2 个正整数 N,M。第 2 到 M+1 行每行包含三个正整数 u,v,w, 表示 u->v 之问存在一条距离为 w 的路。1≤N≤3×10^5,1≤m≤10^6,1<=ui, vi<=N,0≤wi≤10^9。

【输出描述】

输出仅一行,共 N 个数,分别表示从皇宫到编号为 1~N 建筑的最短距离,两两之问用空格隔开。(如果无法到达则输出 -1)

【输入】

3 3

1 2 1

1 3 5

2 3 2

【输出】

0 1 3

【我的题解】(已AC)

import heapq
def dij(s):
    A=[0]*(n+1)   #已找到最短路径顶点的集合
    B=[]
    dis[s]=0
    heapq.heappush(B,(0,s))
    while B:
        u=heapq.heappop(B)[1]
        if A[u]:
            continue
        A[u]=1        #加入A集合
        for v,w in mp[u]:
            if A[v]:
                continue
            if dis[v]>dis[u]+w:
                dis[v]=dis[u]+w
                heapq.heappush(B,(dis[v],v))

n,m=map(int,input().split())
mp=[[] for _ in range(n+1)]   #邻接表存图
INF=1<<64
dis=[INF]*(n+1)     #1到每个点的距离全部初始化为无穷大
for _ in range(m):
    u,v,w=map(int,input().split())
    mp[u].append((v,w))
s=1
dij(s)
for i in range(1,n+1):
    if dis[i]>=INF:
        print(-1,end=" ")
    else:
        print(dis[i],end=" ")

#这样输出竟然也正确
#for i in range(1,n+1):
#    if i==n:
#        if dis[i]>=INF:
#            print(-1)
#        else:
#            print(dis[i])
#    else:
#        if dis[i]>=INF:
#            print(-1,end=" ")
#        else:
#            print(dis[i],end=" ")

以上, Dijkstra算法的入门与应用

祝好

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

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

相关文章

RSTP基础要点(上)

RSTP基础RSTP引入背景STP所存在的问题RSTP对于STP的改进端口角色重新划分端口状态重新划分快速收敛机制&#xff1a;PA机制端口快速切换边缘端口的引入RSTP引入背景 STP协议虽然能够解决环路问题&#xff0c;但是由于网络拓扑收敛较慢&#xff0c;影响了用户通信质量&#xff…

分布式对象存储

参考《分布式对象存储----原理、架构以及Go语言实现》&#xff08;作者&#xff1a;胡世杰&#xff09; 对象存储简介 数据的管理方式 以对象的方式管理数据&#xff0c;一个对象包括&#xff1a;对象的数据、对象的元数据、对象的全局唯一标识符 访问数据的方式 可扩展的分…

useCallback、useMemo、React.memo

1、React.memo React.memo 是 React 中用于函数组件优化的高阶组件&#xff0c;可以在一定程度上减少组件的重渲染&#xff0c;提升应用性能。React.memo 的实现原理是对比组件的前后两次渲染传入的 props 是否相等&#xff0c;如果相等则不会触发重新渲染&#xff0c;否则会触…

使用 Nacos 搭建一个简单的微服务项目

Nacos Nacos 是阿里巴巴推出来的一个新开源项目&#xff0c;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 准备Nacos 将 nacos 安装成功之后&#xff0c;进入nacos的bin 目录下&#xff0c;通过命令sh startup.sh -m standalone启动nacos&#xff0c;然后…

ChatGPT概述:从模型训练到基本应用的介绍

ChatGPT概述&#xff1a;从模型训练到基本应用的介绍 目录 本文是对ChatGPT的由来、训练过程以及实际落地场景的解释&#xff0c;主要内容包括如下三个方面&#xff1a; 1、ChatGPT是什么 2、ChatGPT的原理 3、ChatGPT的思考 4、ChatGPT的应用 ChatGPT是什么 ChatGPT可能是近…

代码随想录算法训练营第四天| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交 、142.环形链表II

24. 两两交换链表中的节点 24.两两交换链表中的节点介绍给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。思路上述是自己看到这道…

Zookeeper3.5.7版本——客户端命令行操作(命令行语法)

目录一、命令行语法二、help命令行语法示例一、命令行语法 命令行语法列表 命令基本语法功能描述help显示所有操作命令ls path使用 ls 命令来查看当前 znode 的子节点 [可监听]-w 监听子节点变化-s 附加次级信息create普通创建-s 含有序列-e 临时&#xff08;重启或者超时消失…

【3.5】单调栈、回文数、子序列、编辑距离问题,MySQL、Redis

文章目录单调栈总结子序列问题总结编辑距离问题总结回文串问题总结MySQL 执行流程是怎样的&#xff1f;第一步&#xff1a;连接器第二步&#xff1a;查询缓存第三步&#xff1a;解析器 解析SQL第四步&#xff1a;执行 SQL2.2 MySQL 一行记录是怎么存储的&#xff1f;MySQL 的数…

ChatGPT vs Bard 背后的技术对比分析和未来发展趋势

ChatGPT vs Bard 背后的技术对比分析和未来发展趋势 目录 ChatGPT vs Bard 背后的技术对比分析和未来发展趋势

Vulnhub系列:VulnOSv2

老样子&#xff0c;kali ip:192.168.56.104&#xff0c;靶机ip利用nmap或arp-scan -l进行查看靶机ip为&#xff1a;192.168.56.124&#xff0c;利用nmap进行端口探测发现了22、80、6667端口&#xff0c;下一步就是进行web探测&#xff0c;输入靶机ip后发现页面存在个链接&#…

Qt中调用gtest进行单元测试及生成覆盖率报告

一.环境配置 googletest地址:https://github.com/google/googletest 我下载的是1.12.1,这是最后一个支持C++11的版本。 首先编译gtest,在windows上的编译方式和编译gRPC一模一样,详见Qt中调用gRPC,编译完了会生成几个静态库,如下图所示 本文主要用到了libgtest.a 下载ms…

多线程二 多线程了解与使用

文章目录synchronized 锁有两种synchronized异常捕获主线程和子线程volatile的作用notify是随机启动等待线程中的一个synchronized 锁有两种 类对象类的实例 第一种&#xff1a;锁类对象&#xff0c;有两种方式&#xff0c;如下&#xff1a; // 方法一&#xff1a;synchroni…

Dubbo源码解析-——服务导出

前言 在之前我们讲过Spring和Dubbo的集成&#xff0c;我们在服务上标注了DubboService的注解&#xff0c;然后最终Dubbo会调用到ServiceBean#export方法中&#xff0c;本次我们就来剖析下服务导出的全流程。 一、前置回顾 由于ServiceBean实现了ApplicationListener接口&…

基于图像识别的数据处理系统

基于EASYDL模型的图像识别数据处理系统 需求分析 1.1软件背景分析 世界已经进入工业自动化的时代。随着图像识别、语音识别、机械稳定化的发展。自动化已经成为公司或者企业发展的重要方向。自动化是指机器设备或生产过程在不需要人工直接干预情况下&#xff0c;按照预期的目…

Java分布式解决方案(二)

文章目录&#x1f525;分布式事务处理_认识本地事务&#x1f525;关系型数据库事务基础_并发事务带来的问题&#x1f525;关系型数据库事务基础_MySQL事务隔离级别&#x1f525;MySQL事务隔离级别_模拟异常发生之脏读&#x1f525;MySQL事务隔离级别_模拟异常发生之不可重复读&…

浏览器渲染原理

阶段 - Parse 1、解析HTML&#xff0c;浏览器将从服务器获取到的HTML文件之后&#xff0c;会产生一个渲染任务&#xff0c;交给消息队列&#xff08;EventLoop/MessageLoop&#xff09;。 2、在事件循环机制的作用下&#xff0c;会将渲染任务交给主线程 3、主线程在获取到渲染…

入门vue(1-10)

正确学习方式&#xff1a;视频->动手实操->压缩提取->记录表述 1基础结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"&…

LeetCode 1599. 经营摩天轮的最大利润

【LetMeFly】1599.经营摩天轮的最大利润 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-profit-of-operating-a-centennial-wheel/ 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱 最多可以容纳 4 位游客 。你可以 逆时针 轮…

0103深度优先搜索和单点连通-无向图-数据结构和算法(Java)

文章目录1.1 走迷宫1.2 图的深度优先搜索实现1.3 算法分析及性能1. 4 单点连通性后记1.1 走迷宫 简单的迷宫&#xff0c;如下图1.1-1所示&#xff1a; 探索迷宫而不迷路&#xff0c;我们需要&#xff1a; 选择一条没有标记过的通道&#xff0c;在你走过的路上铺一条绳子&…

基于linux 实现DNS Client请求

DNS是什么&#xff1a; DNS是域名系统,Domain Name System的缩写,是一个服务。 作用&#xff1a; DNS就是把域名解析为IP地址&#xff0c;提供我们上网&#xff0c;我们能够上网最终是找到IP地址。 DNS请求报文格式&#xff1a; 分别包含 Transaction ID&#xff1a;会话标…