最短路: Djikstra

news2024/9/21 2:38:42

最短路: Djikstra


  • 适用于边权非负

    如果存在负边权, 则当前距离dist最小的点, 不一定就是实际离源点最近的点,可能有负边导致其它路径离当前点更近

    如下图所示, 如果存在负边, y点距离S点最近, 所以选中y点进行松弛,

    image-20230821111655979
  • 贪心思想

  • 当边权非负,离起点S最近的点,不能被更新, 如果在中间加入一个点,则长度必然大于当前距离

  • 在稀疏图中.使用二叉堆实现的 Dijkstra 算法较 Bellman-Ford 算法具有较大的效率优势;

  • 而在稠密图中,这时候使用暴力做法较二叉堆实现更优。

最短路

  • 暴力
  • 时间复杂度
    • 不使用任何数据结构进行维护,每次 2 操作执行完毕后,直接在 集合中暴力寻找最短路长度最小的结点。2 操作总时间复杂度为 ,1 操作总时间复杂度为 ,全过程的时间复杂度为 。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 5e3+5;
const int INF = 0x3f3f3f3f;
int dist[N];
bool distOver[N];
vector<PII> edges[N];
int n, m, k;
void djikstra(int s, int t) {
    memset(dist, 0x3f, sizeof(dist));
    memset(distOver, false, sizeof(distOver));
    dist[s] = 0;
    for (int i = 1; i <= n; i++) {
        int u = -1;
        for (int j = 1; j <= n; j++) {
            if (!distOver[j] && dist[j] < INF) {
                if (u == -1 || dist[j] < dist[u]) {
                    u = j;
                }
            }
        }
        if (u == -1) break;
        distOver[u] = true;
        for (auto [v, w] : edges[u]) {
            dist[v] = min(dist[v], dist[u] + w);
        }
    }
    if (dist[t] < INF) cout << dist[t] << endl;
    else cout << -1 << endl;

}
int main() {
	cin >> n >> m >> k;
    while (m--) {
		int u, v, w;
		cin >> u >> v >> w;
    	edges[u].push_back({v, w});
    }
    while (k--) {
		int s, t;
		cin >> s >> t;
    	djikstra(s, t);
    }
    return 0;
}

最短路2


堆优化

使用升序排列的优先队列

distOver[u]表示结点u的距离已经确定

每从堆中取出最近的点, 则S到这个点的最短距离已经确定

再从这个点开始尝试松弛, 其它未确定的点的距离

  • 时间复杂度

    和二叉堆类似,但使用优先队列时,如果同一个点的最短路被更新多次,因为先前更新时插入的元素不能被删除,也不能被修改,只能留在优先队列中,故优先队列内的元素个数是O(m)的,

    时间复杂度为 O ( m ∗ l o g m ) O(m*logm) O(mlogm)

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5+5;
const int INF = 0x3f3f3f3f;
bool distOver[N];
int dist[N];
vector<pair<int, int>> edge[N];
void Djikstra(int s, int t) {
	memset(dist, 0x3f, sizeof(dist));
	memset(distOver, false, sizeof(distOver));
	priority_queue<PII, vector<PII>, greater<PII>> q;
	dist[s] = 0;
	q.push(make_pair(dist[s], s));
	while (!q.empty()) {
		int u = q.top().second; 
		q.pop();
		if(distOver[u]) continue;
		distOver[u] = true;
		for(auto [v, w] : edge[u]) {
			if(dist[u] + w < dist[v]) {
				dist[v] = dist[u] + w;
				q.push({dist[v], v});
			}
		}
	}
	if(dist[t] < INF) printf("%d\n", dist[t]);
	else puts("-1");
} 
int main() {
	int n, m, k;
	cin >> n >> m >> k;
    while (m--) {
		int u, v, w;
		cin >> u >> v >> w;
    	edge[u].push_back({v, w});
    }
    while (k--) {
		int s, t;
		cin >> s >> t;
    	Djikstra(s, t);
    }
    return 0;
}

租房

因为是无向图, 所以st的最短距离就是ts的最短距离

  • 正向思维
    • 对每个点跑Djikstra,求得到那三个点的最短距离, 然后取最小值
  • 逆向思维
    • 从其余点到那三个点的最短距离就等于那三个点到其余点的最短距离
    • 对那三个点各跑一次Djikstra, 求得三个点到其余个点的最短距离
    • 再遍历各点, 算出各点到那三个点的最短距离之和, 取min
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 5e3+5;
const int INF = 0x3f3f3f3f;
int n, m, a, b, c;
vector<PII> edges[N];
int dist[N];
int f[3][N];
bool distOver[N];
void djikstra(int k, int s) {

    memset(dist, 0x3f, sizeof(dist));
    memset(distOver, false, sizeof(distOver));
    
    dist[s] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> q;
    q.push({dist[s], s});
    
    while (!q.empty()) {
        int u = q.top().second;
        q.pop();
        if (distOver[u]) continue;
        distOver[u] = true;
        for (auto [v, w] : edges[u]) {
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                q.push({dist[v], v});
            }
        }
    }    
    memcpy(f[k], dist, sizeof(dist));
}
int main() {
    cin >> n >> m;
    while (m--) {
        int u, v, w;
        cin >> u >> v >> w;
        edges[u].push_back({v, w});
        edges[v].push_back({u, w});
    }
    cin >> a >> b >> c;
    djikstra(0, a);
    djikstra(1, b);
    djikstra(2, c);    
    int ans = INF;
    // 3行n列, 按列求和, 求列和的最小值, 
    // 对应列序号的点即为到3个点的最近点
    // 列和即为到3个点的最短距离之和
    for (int i = 1; i <= n; i++) {
        int temp = f[0][i] + f[1][i] + f[2][i];
        ans = min(ans, temp);
    }
    cout << ans << endl;
    return 0;
}

聚会


所有同学周末要到小蜗家聚会,聚会结束后同学们都会回家。为了合理安排时间,小蜗想要知道对于在路上来回花费时间最长的同学,他在路上要花费多少时间。

题目说的是来回花费时间最大的点

s点到其它点的距离很好求, 直接在s点处跑djistra即可获得到其余点的最短距离

但由于是有向图, 其余点到s点的最短距离并不等于s点到其余点的最短距离

如何求其余n-1个点到s点的最短距离?

暴力想法: 枚举其余n-1个点, 对每个点跑一次djistra, 求出n-1个点到目标点的最短距离, 求他们的最大值, 显然时间复杂度为: O ( n m l o g m ) O(nmlogm) O(nmlogm)

优化: 其余n-1个点到s的距离等于在反图中, s点到其余点的最短距离

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5+5;
const int INF = 0x3f3f3f3f;
int n, m, k;
vector<PII> edges[2][N];
int dist[N];
int f[2][N];
bool distOver[N];
void djikstra(int k, int s) {

    memset(dist, 0x3f, sizeof(dist));
    memset(distOver, false, sizeof(distOver));
    
    dist[s] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> q;
    q.push({dist[s], s});
    
    while (!q.empty()) {
        int u = q.top().second;
        q.pop();
        if (distOver[u]) continue;
        distOver[u] = true;
        for (auto [v, w] : edges[k][u]) {
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                q.push({dist[v], v});
            }
        }
    }    
    memcpy(f[k], dist, sizeof(dist));
}
int main() {
    cin >> n >> m >> k;
    while (m--) {
        int u, v, w;
        cin >> u >> v >> w;
        edges[0][u].push_back({v, w});
        edges[1][v].push_back({u, w});
    }
    djikstra(0, k);
    djikstra(1, k);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        int temp = f[0][i] + f[1][i];
        ans = max(ans, temp);
    }
    cout << ans << endl;
    return 0;
}

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

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

相关文章

PointNet++改进策略 :模块改进 | SPVConv, 体素和点云特征融合提升小目标检测能力

论文题目&#xff1a;Searching Efficient 3D Architectures with Sparse Point-Voxel Convolution发布期刊&#xff1a;ECCV通讯地址&#xff1a;麻省理工 & 清华大学代码地址&#xff1a;https://github.com/mit-han-lab/spvnas 介绍 这篇论文的主题是如何为自驾车等应…

[译] Go语言的源起,发展和未来

本篇内容是根据2019年9月份Creating the Go programming language音频录制内容的整理与翻译, 两位主持人与Go 的创始人 Rob Pike 和 Robert Griesemer谈论了 Go 的起源、发展、影响和未来。这是一个史诗般的剧集&#xff0c;深入探讨了 Go 的历史和详细信息&#xff0c;以及他们…

手动部署并测试内网穿透(ssh 和 nginx)

原理回顾 首先需要一台连接了公网的云服务器&#xff0c;然后我们要访问的内网穿透对象最好是Linux服务器&#xff0c;比如虚拟机&#xff0c;然后我们通过向云服务器发送指令&#xff0c;云服务器再将指定发送给指定对象&#xff0c;让其能够执行命令。 总结就是&#xff1a…

数据结构与算法——Java实现 6.递归

要学会试着安静下来 —— 24.9.17 一、递归的定义 计算机科学中&#xff0c;递归是一种解决计算问题的方法&#xff0c;其中解决方案取决于同一类问题的更小子集 说明: ① 自己调用自己&#xff0c;如果说每个函数对应着一种解决方案&#xff0c;自己调用自己意味着解决方案是…

数据建模无法满足复杂业务需求?别慌,数据开发平台可以完美互补!

前言 数据可视化建模无论是对于企业的数字化转型&#xff0c;还是对数据资源的价值开发来说&#xff0c;都是至关重要的工具&#xff0c;小兵在前文《数据可视化建模平台介绍》。中有详细介绍过他的能力&#xff0c;包括面向多源异构的企业数据&#xff0c;为企业提供数据集成…

web基础—dvwa靶场(十一)CSP Bypass

CSP Bypass(CSP 绕过) 内容安全策略&#xff08;CSP&#xff09;用于定义脚本和其他资源可以从何处加载或执行&#xff0c;本模块将指导您根据开发人员犯下的常见错误来绕过该策略。 这些漏洞都不是 CSP 中的实际漏洞&#xff0c;它们都是实现 CSP 的方式中的漏洞。 绕过内容安…

xtop:如何debug fail reason

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 fix_xx_violations之后,工具会报告fail reason summary,通过man reason_name可以获知fail原因&#x

STM32(十六):MPU6050简介

MPU6050 MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0c;可进一步得到姿态角&#xff0c;常应用于平衡车、飞行器等需要检测自身姿态的场景。 3轴加速度计&#xff08;Accelerometer&#…

攻防世界--->gametime

做题笔记。 前言&#xff1a; 因为有意思&#xff0c;所以&#xff0c;&#xff0c;&#xff0c;打通关了。。哈哈哈。 题外话&#xff1a;哦&#xff0c;程序结果还在&#xff0c;是因为我是在WSL—Debian上运行的。你还别说&#xff0c;真挺好用的&#xff0c;vm虚拟机能不…

Node-RED和物联网分析:实时数据处理和可视化平台

这篇论文的标题是《Node-RED and IoT Analytics: A Real-Time Data Processing and Visualization Platform》&#xff0c;发表在《Tech-Sphere Journal of Pure and Applied Sciences (TSJPAS)》2024年第一期上。论文主要探讨了Node-RED和物联网分析在物联网(IoT)实时数据处理…

列表、数组排序总结:Collections.sort()、list.sort()、list.stream().sorted()、Arrays.sort()

列表类型 一.Collections.sort() Collections.sort()用于List类型的排序&#xff0c;其提供了两个重载方法&#xff1a; 1.sort(List<T> list) &#xff08;1&#xff09;List指定泛型时只能指定引用数据类型&#xff0c;也就是说无法用于基本数据类型的排序。 &am…

9.20作业

手动封装一个顺序表&#xff08;SeqList&#xff09;,分文件编译实现 有私有成员&#xff1a; 顺序表数组的起始地址 ptr、 顺序表的总长度&#xff1a;size、顺序表的实际长度&#xff1a;len 成员函数&#xff1a; 初始化 init(int n) 判空&#xff1a;empty 判满&#xff1…

Rust语言入门第七篇-控制流

文章目录 Rust语言入门第七篇-控制流If 表达式基本结构特点和规则示例 let 语句中使用 ifloop 循环基本结构特点示例综合示例 while 循环基本结构特点示例综合示例 与 loop 循环的区别 for 循环基本结构详细说明特点示例综合示例 match 表达式match表达式的语法结构示例代码 Ru…

Mysql存储过程详细解读

目录 存储过程介绍 创建与调用 查看与删除 变量 系统变量 用户自定义变量 ​编辑局部变量 ​编辑​编辑IF判断 存储过程参数​编辑​编辑​编辑 CASE ​编辑 WHILE​编辑 ​编辑REPEAT​编辑​编辑 LOOP 游标 条件处理程序 存储函数 存储过程介绍 创建与调用 查…

GNN-RAG:用于大模型推理的图神经检索

GNN-RAG&#xff1a;用于大模型推理的图神经检索 秒懂大纲提出背景解法拆解全流程优化创意总结 论文&#xff1a;GNN-RAG: Graph Neural Retrieval for Large Language Model Reasoning 代码&#xff1a;https://github.com/cmavro/GNN-RAG 秒懂大纲 ├── GNN-RAG【主题】…

【刷题日记】43. 字符串相乘

43. 字符串相乘 其实就是大数乘法题&#xff0c;这道题用草稿纸演练一下&#xff0c;其实很好找到方法&#xff0c;模拟大数乘法即可。需要注意的是进位和迭代值&#xff0c;还有注意向下取整和去除前导0&#xff08;容易遗漏&#xff09;。去除前导0的时候还要注意如果全是0&…

命令行运行python时找不到模块怎么解决

问题&#xff1a; 新建了一个项目&#xff0c;目录结构如下&#xff1a; 然后在pycharm中运行glovar是没有问题的&#xff0c;但是在命令行中运行就会提示找不到init模块。 这是因为在pycharm中运行的时候&#xff0c;pycharm会自动将项目所在目录添加到了sys.path中&#xf…

天宝Trimble RealWorks2024.0.2注册机 点云后处理软件 点云三维重建软件

一、功能特色 1、强大的点云数据处理平台 Trimble Realworks2024是市面上先进的点云数据处理软件&#xff0c;能够配准、可视化、浏览和直接处理市面上几乎所有主流品牌扫描仪点云数据&#xff0c;包括Leica、Riegl、ZF、Faro、Topcon等。 2、业界领先的无目标全自动配准 T…

Apache Flink 流批融合技术介绍

摘要&#xff1a;本文整理自阿里云高级研发工程师、Apache Flink Contributor 周云峰老师在 Apache Asia CommunityOverCode 2024中的分享。内容主要分为以下三个部分&#xff1a; 从流批一体到流批融合流批融合的技术解决方案社区进展及未来展望 一、从流批一体到流批融合 1&…

记忆化搜索专题——算法简介力扣实战应用

目录 1、记忆化搜索算法简介 1.1 什么是记忆化搜索 1.2 如何实现记忆化搜索 1.3 记忆化搜索与动态规划的区别 2、算法应用【leetcode】 2.1 题一&#xff1a;斐波那契数 2.1.1 递归暴搜解法代码 2.1.2 记忆化搜索解法代码 2.1.3 动态规划解法代码 2.2 题二&#xff1…