【贪心算法】Dijkstra 算法及其衍生

目录

  • Dijkstra 算法
  • Dijkstra 算法正确性
    • 证明
  • Dijkstra 算法的复杂度
    • 优化
  • Dijkstra 算法的衍生
  • SSSP的应用

Dijkstra 算法

1959 年,Edsger Dijkstra 提出一个非常简单的贪心算法来求解单源最短路径问题(Single-Source Shortest Path,SSSP)。

我们开始来描述这个算法,它确定从源点s 到图的每个其他结点的最短路径的长度,同时也容易确定这些路径。算法维护结点的集合 S S S ,对于这些结点我们已经确定了从 s 出发的最短距离 d(u)

  1. 这是图“已被探查”的部分初始: S = { s } S=\{s\} S={s} ,且 d ( s ) = 0 d(s)=0 d(s)=0

  2. 现在对每个结点 v ∈ V − S v\in V-S vVS 我们确定一条最短路径,它可以沿一条穿过已被探查部分 S 的路径旅行到某个 u ∈ S u\in S uS ,然后再沿着一条边 ( u , v ) (u,v) (u,v) 而把这条路径构造出来,即我们考虑量 d ′ ( v ) = min ⁡ e = ( u , v ) : u ∈ S d ( u ) + l e d'(v)=\min_{e=(u,v):u\in S}d(u)+l_e d(v)=mine=(u,v):uSd(u)+le

  3. 我们选择结点 v ∈ V − S v\in V-S vVS 使得这个量最小,将 v v v 加到 S S S 中,并且定义 d ( v ) d(v) d(v) d ′ ( v ) d'(v) d(v)的值。

在这里插入图片描述

生成与 Dijkstra 算法找到的距离相对应的 s➡u 路径 P u P_u Pu 是简单的:

  • 当每个结点 v v v 被加到集合 S S S 时,只需要记录一条达到值 min ⁡ e = ( u , v ) : u ∈ S d ( u ) + l e \min_{e=(u,v):u\in S}d(u)+l_e mine=(u,v):uSd(u)+le 的边 ( u , v ) (u,v) (u,v)
    路径 P v P_v Pv 隐含地由这些边描绘出来:
    • 为构造 P_v,我们只不过从 v v v 开始,沿反方向跟随对 v v v 存入的边到 u u u
      然后沿反方向跟随对 u u u 存入的边到它的祖先,并且继续下去直到我们到达源点 s s s

Dijkstra 算法正确性

证明算法的正确性即证明路径 P u P_u Pu 确实是最短路径

Diikstra 算法在下述意义上是贪心法,我们用一条边加上一支在 S 中的路径总可以构造一支最短的新的 s-v 路径。通过归纳证明它“领先于”所有其他的解,即确定每一次它选了一条到结点 v v v 的路径,这条路径比每条到的其他可能的路径都要短。

证明

通过在 S 的大小上的归纳来证明这个定理;

  • ∣ S ∣ = 1 |S|=1 S=1 此时有 S = s S={s} S=s d ( s ) = 0 d(s)=0 d(s)=0
  • ∣ S ∣ = k , k ≥ 1 |S|=k,k≥1 S=k,k1 时,加入结点 v v v 使得 ∣ S ∣ = k + 1 |S|=k+1 S=k+1 ,令 ( u , v ) (u,v) (u,v) 是路径上的最后一条边

根据归纳假设:路径 P u P_u Pu 是对某个结点 u ∈ S u\in S uS 的最短 s-u 路径
考虑任意其他的 s-v 路径 P P P,要证明它至少与 P v P_v Pv 一样长,为了到达 v v v ,这条路径 P P P 一定在某个地方离开集合 S S S

y y y 是在 P P P 上但不在 S S S 中的第一个结点,且设 x ∈ S x\in S xS 是紧接在 y y y 前面的结点,如下图所示

在这里插入图片描述
证明的关键非常简单: P P P 不可能比 P v P_v Pv 短,因为到它离开集合 S S S 的时刻至少已经与 P v P_v Pv 一样长。在第 k + 1 k+1 k+1 次选代中,Diikstra 算法一定已经考虑过通过边 ( x , y ) (x,y) (x,y) 把结点 y y y 加到 S S S,但是由于 v v v 更有利而放弃了这个选择。这就意味着没有从 s s s 经过到 y y y 且比 P v P_v Pv 更短的路径。同时 P P P 中到 y y y 为止的子路径是至少与 P v P_v Pv 一样长的路径

P ′ P' P 代表 P P P 的从 s s s x x x 的子路径。

  • 因为 x ∈ S x\in S xS ,根据归纳假设 P x P_x Px 是最短的 s-x 路径,且长度为 d ( x ) d(x) d(x) ,因此 l ( P ′ ) ≥ l ( P x ) = d ( x ) l(P')\ge l(P_x)=d(x) l(P)l(Px)=d(x)

  • 于是 P P P 的到结点 y y y 的子路径 l ( P ) l(P) l(P) 有长度 l ( P ′ ) + l ( x , y ) ≥ d ( x ) + l ( x , y ) ≥ d ′ ( y ) l(P')+l(x,y)\ge d(x)+l(x,y) \ge d'(y) l(P)+l(x,y)d(x)+l(x,y)d(y)

  • 因为 Dijkstra 算法在这次迭代中选择了 v v v 而不是 y y y 所以 d ′ ( y ) ≥ d ′ ( v ) = l ( P v ) d'(y)\ge d'(v)=l(P_v) d(y)d(v)=l(Pv)

上述不等式组合起来可证明: l ( P ) ≥ l ( P ′ ) + l ( x , y ) ≥ l ( P v ) l(P)\ge l(P')+l(x,y)\ge l(P_v) l(P)l(P)+l(x,y)l(Pv)


Dijkstra 算法的复杂度

  • 对于具有 n n n 个结点的图:While 循环的迭代有 n − 1 n-1 n1 次,每次迭代把一个新结点 v v v 加到 S S S 中。有效选择正确的结点 v v v 是比较复杂的事情。如果考虑每个结点 v ∈ S v\in S vS 并且检查所有在 S S S v v v 之间的边以确定最小值
  • 对于具有 m m m 条边的图,计算所有这些最小值可能用 O ( m ) O(m) O(m) 时间
  • 运行时间为 O ( m n ) O(mn) O(mn)

优化

对于最小值的确定可以采取一定的优化措施
对每个结点 v ∈ V − S v\in V-S vVS 维护最小值 d ′ ( v ) = min ⁡ e = ( u , v ) , u ∈ S d ( u ) + l e d'(v)= \min_{e=(u,v),u\in S} d(u)+l_e d(v)=mine=(u,v),uSd(u)+le ,而不是在每次迭代时重新计算
同时将 V-S 的结点保存在一个以 d ′ ( v ) d'(v) d(v) 作为其关键字的优先队列里来进一步改进算法的效率

  • 优先队列:用于维护 n 个元素集合的数据结构,每个元素具有一个关键字。一个优先队列可以有效地插入元素、删除元素、改变一个元素的关键字以及取出具有最小关键字的元素。

使用优先队列,Dijkstra 算法可以在具有 n 个结点和 m 条边的图上,实现运行在 O ( m ) O(m) O(m) 时间,加上 n 次 ExtractMin 操作和 m 次ChangeKey 操作的时间.

每个优先队列的操作可以运行在 O ( log ⁡ n ) O(\log n) O(logn) 时间

于是对于这个实现的总时间是 O ( m log ⁡ n ) O(m\log n) O(mlogn)

import heapqdef dijkstra(graph, start):distances = {node: float('inf') for node in graph}distances[start] = 0priority_queue = [(0, start)]while priority_queue:current_distance, current_node = heapq.heappop(priority_queue)if current_distance > distances[current_node]:continuefor neighbor, weight in graph[current_node].items():distance = current_distance + weightif distance < distances[neighbor]:distances[neighbor] = distanceheapq.heappush(priority_queue, (distance, neighbor))return distances# Example graph
graph = {'A': {'B': 4, 'C': 2},'B': {'A': 4, 'C': 5, 'D': 10},'C': {'A': 2, 'B': 5, 'D': 3},'D': {'B': 10, 'C': 3}
}
start_node = 'A'result = dijkstra(graph, start_node)
print("Shortest distances from node", start_node, "to all other nodes:", result)

Dijkstra 算法的衍生

priority queueINSERTDELETE-MINDECREASE-KEYtotal
Node-indexed array
(A[i] = priority of i)
O ( 1 ) O(1) O(1) O ( n ) O(n) O(n) O ( 1 ) O(1) O(1) O ( n 2 ) O(n^2) O(n2)
Binary heap O ( log ⁡ n ) O(\log n) O(logn) O ( log ⁡ n ) O(\log n) O(logn) O ( log ⁡ n ) O(\log n) O(logn) O ( m log ⁡ n ) O(m\log n) O(mlogn)
D-way heap
(Johnson 1975)
O ( d log ⁡ d n ) O(d\log _dn) O(dlogdn) O ( d log ⁡ d n ) O(d\log _dn) O(dlogdn) O ( log ⁡ d n ) O(\log _dn) O(logdn) O ( m log ⁡ m / n n ) O(m\log _{m/n} n) O(mlogm/nn)
Fibonacci heap
(Fredman–Tarjan 1984)
O ( 1 ) O(1) O(1) O ( log ⁡ n ) O(\log n) O(logn) O ( 1 ) O(1) O(1) O ( m + n log ⁡ n ) O(m+n\log n) O(m+nlogn)
Integer priority queue
(Thorup 2004)
O ( 1 ) O(1) O(1) O ( log ⁡ log ⁡ n ) O(\log \log n) O(loglogn) O ( 1 ) O(1) O(1) O ( m + n log ⁡ log ⁡ n ) O(m+n\log \log n) O(m+nloglogn)

SSSP的应用

  • PERT/CPM(计划评审技术/关键路径法)
  • 地图导航
  • 缝隙雕刻(Seam Carving)
  • 机器人导航
  • 纹理映射
  • LaTeX排版
  • 城市交通规划
  • 电话营销员排班
  • 电信消息路由
  • 网络路由协议(OSPF, BGP, RIP)
  • 根据给定交通拥堵模式的最佳卡车路线

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

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

相关文章

[C#]使用PaddleInference图片旋转四种角度检测

官方框架地址】 https://github.com/PaddlePaddle/PaddleDetection.git 【算法介绍】 PaddleDetection 是一个基于 PaddlePaddle&#xff08;飞桨&#xff09;深度学习框架的开源目标检测工具库。它提供了一系列先进的目标检测算法&#xff0c;包括但不限于 Faster R-CNN, Ma…

一张照片来跳舞,AI带去你跳科目三

大家好我是在看&#xff0c;记录普通人学习探索AI之路。 重生之我是秦始皇&#xff0c;起猛了看见兵马俑在跳舞。 最近&#xff0c;随着社交媒体上热议的科目三话题热度持续飙升&#xff0c;阿里集团旗下的通义千问项目团队精准把握住了这一社会潮流&#xff0c;借势推出了一…

PHP 基础编程 1

文章目录 前后端交互尝试php简介php版本php 基础语法php的变量前后端交互 - 计算器体验php数据类型php的常量和变量的区别php的运算符算数运算符自增自减比较运算符赋值运算符逻辑运算 php的控制结构ifelseelse if 前后端交互尝试 前端编程语言&#xff1a;JS &#xff08;Java…

OpenHarmony鸿蒙源码下载编译和开发环境搭建

目录 一、开发环境搭建和源码下载二、编译三、总结 一、开发环境搭建 最好是在如Ubuntu18.04以上的系统中搭建&#xff0c;不然有些软件依赖需要解决&#xff0c;加大搭建时间 如gitee中开源OpenHarmony中的文档所示&#xff0c;搭建开发环境&#xff0c;搭建文档网站如下&a…

Supershell反溯源配置

简介 项目地址&#xff1a;https://github.com/tdragon6/Supershell Supershell是一个集成了reverse_ssh服务的WEB管理平台&#xff0c;使用docker一键部署&#xff08;快速构建&#xff09;&#xff0c;支持团队协作进行C2远程控制&#xff0c;通过在目标主机上建立反向SSH隧…

【Java EE初阶六】多线程案例(单例模式)

1. 单例模式 单例模式是一种设计模式&#xff0c;设计模式是我们必须要掌握的一个技能&#xff1b; 1.1 关于框架和设计模式 设计模式是软性的规定&#xff0c;且框架是硬性的规定&#xff0c;这些都是技术大佬已经设计好的&#xff1b; 一般来说设计模式有很多种&#xff0c;…

Go语言之父:开源14年,Go不止是编程语言,究竟做对了哪些?

提及编程语言&#xff0c;2023 年&#xff0c;除了老牌的 C 和新晋之秀 Rust 热度最高之外&#xff0c;就要数 Go 了。 从 2009 年由 C 语言获取灵感而发布&#xff0c;到如今风靡已久的高性能语言&#xff0c;Go 已经走过了 14 个年头。 “Go是一个项目&#xff0c;不只是一门…

基于ssm的智慧社区电子商务系统+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

HTML5大作业-精致版个人博客空间模板源码

文章目录 1.设计来源1.1 博客主页界面1.2 博主信息界面1.3 我的文章界面1.4 我的相册界面1.5 我的工具界面1.6 我的源码界面1.7 我的日记界面1.8 我的留言板界面1.9 联系博主界面 2.演示效果和结构及源码2.1 效果演示2.2 目录结构2.3 源代码 源码下载 作者&#xff1a;xcLeigh …

在MS中基于perl脚本实现氢键统计

氢原子与电负性大的原子X以共价键结合&#xff0c;若与电负性大、半径小的原子Y&#xff08;O F N等&#xff09;接近&#xff0c;在X与Y之间以氢为媒介&#xff0c;生成X-H…Y形式的一种特殊的分子间或分子内相互作用&#xff0c;称为氢键。 氢键通常是物质在液态时形成的&…

第1章 线性回归

一、基本概念 1、线性模型 2、线性模型可以看成&#xff1a;单层的神经网络 输入维度&#xff1a;d 输出维度&#xff1a;1 每个箭头代表权重 一个输入层&#xff0c;一个输出层 单层神经网络&#xff1a;带权重的层为1&#xff08;将权重和输入层放在一起&#xff09; 3、…

数据库设计——DML

D M L \huge{DML} DML DML&#xff1a;数据库操作语言&#xff0c;用来对数据库中的数据进行增删改查。 增&#xff08;INSERT&#xff09; 使用insert来向数据库中增加数据。 示例&#xff1a; -- DML : 数据操作语言 -- DML : 插入数据 - insert -- 1. 为 tb_emp 表的 us…

Kubernetes二进制部署 单节点

一、环境准备 k8s集群master1&#xff1a;192.168.229.90 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群node1: 192.168.229.80 kubelet kube-proxy docker flannel k8s集群node2: 192.168.229.70 kubelet kube-proxy docker flannel 至少2C2G 常见的k…

Flutter3.X基础入门教程(2024完整版)

Flutter介绍&#xff1a; Flutter是谷歌公司开发的一款开源、免费的UI框架&#xff0c;可以让我们快速的在Android和iOS上构建高质量App。它最大的特点就是跨平台、以及高性能。 目前Flutter已经支持 iOS、Android、Web、Windows、macOS、Linux的跨平台开发。 教程所讲内容支持…

独立式键盘控制步进电机实验

#include<reg51.h> //包含51单片机寄存器定义的头文件 sbit S1P1^4; //将S1位定义为P1.4引脚 sbit S2P1^5; //将S2位定义为P1.5引脚 sbit S3P1^6; //将S3位定义为P1.6引脚 unsigned char keyval; //储存按键值 unsigned char ID; …

bat批处理文件_命令汇总(2)

文章目录 1、换行2、返回上一级目录cd..3、隐藏指令回显echo off4、开启指令回显echo on5、用关闭echo off指令本身的回显6、echo提示信息 1、换行 cd.. echo. echo. echo. pause2、返回上一级目录cd… 3、隐藏指令回显echo off echo off echo hello1 echo hello2 pause4、开…

tomcat session cookie值设置逻辑

tomcat session cookie 值设置&#xff0c;tomcat jsessionid设置 ##调用request.getSession() Controller RequestMapping("/cookie") public class CookieController {RequestMapping("/tomcatRequest")ResponseBodypublic String tomcatRequest(HttpS…

软件测试|什么是Python构造方法,构造方法如何使用?

构造方法&#xff08;Constructor&#xff09;是面向对象编程中的重要概念&#xff0c;它在创建对象时用于初始化对象的实例变量。在Python中&#xff0c;构造方法是通过特殊的名称__init__()来定义的。本文将介绍Python构造方法的基本概念、语法和用法。 什么是构造方法&…

轻松获取CHATGPT API:免费、无验证、带实例

免费获取和使用ChatGPT API的方法 快速开始&#xff1a;视频教程 章节一&#xff1a;GPT-API-Free开源项目介绍 GPT-API-Free 是一个开源项目&#xff0c;它提供了一个中转API KEY&#xff0c;使用户能够调用多个GPT模型&#xff0c;包括gpt-3.5-turbo、embedding和gpt-4。这…

记一次服务器被入侵的排查过程

起因 阿里云安全中心报告了告警信息&#xff0c;同时手机短信、邮件、电话也接收到了来自阿里云的风险通知&#xff0c;感觉这方面阿里云还是不错。 排查及解决过程 这条wget指令究竟是怎么被运行的 我无法定位到攻击人员是通过什么样的方式让我的java程序执行了wget这条指…