图论:Dijkstra算法

昨天介绍了最小生成树的两个算法,最小生成树的两个算法旨在求解无向有权图中的最小代价联通图的问题,那么对于有向有权图,从起点到终点的最小花费代价问题就可以用 Dijkstra 算法来解决而且Dijkstra算法可以求出来从起始点开始到所有节点的最短距离!他和最小生成树的prim算法十分类似,也是三部曲,最短路是图论中的经典问题即:给出一个有向图,一个起点,一个终点,问起点到终点的最短路径。

朴素版Dijkstra算法

dijkstra算法:在有权图(权值非负数)中求从起点到其他节点的最短路径算法。

  • dijkstra 算法可以同时求起点到所有节点的最短路径
  • 权值不能为负数

dijkstra三部曲

  1. 第一步,选源点到哪个节点近且该节点未被访问过
  2. 第二步,该最近节点被标记访问过
  3. 第三步,更新非访问节点到源点的距离(即更新ans数组)

ans数组用来记录每一个节点距离起始点的最小距离。

循环n次,每一次都能确定一个最优点(其实和prim算法一样都是用了贪心的策略,因为之后的所有的点的选取都是基于目前所有的可达路径,所以要在当前所有的可达路径中选一个权值最小的路径,以其为基准再继续更新之后的可达点,当一个点被更新到最短路中的时候【即被标记访已访问的时候】,就说明在他之前所有可以到达他的路径都遍历过了,因为他是被所有的前面的可达他的点都遍历过的)。

说多了容易迷糊,来看一个模版题来促进对算法以及代码模板的理解

参加科学大会

题目链接:参加科学大会

这道题还是相对简单一点的,因为已经固定了起点是1,终点是n,所以不需要对起点和终点进行分析,直接套用模板即可。注意建图的时候如果用邻接矩阵时开[n][n]二维数组m只是边数!

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f3f3f3f3f;
int n,m;void solve()
{cin>>n>>m;vector<vector<int>> e(n+1,vector<int>(n+1,inf));//建图vector<bool> v(n+1,false);//标记数组vector<int> ans(n+1,inf);//所有的点到起点的最短距离(最小代价)for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u][v] = w;//建图}ans[1] = 0;//Dijkstra算法三部曲for(int i=1;i<=n;i++){int mi = inf;int index = 0;//遍历找不在未访问的距离起点最近的点for(int j=1;j<=n;j++)//因为之后的所有答案都会在现在的路径基础上累加 所以在现有路径中挑最短的{if(!v[j] && ans[j] < mi){mi = ans[j];index = j;}}//将最近点标记为已访问v[index] = true;//更新所有未访问的可达点到起点的最短距离for(int j=1;j<=n;j++){if(!v[j] && e[index][j] + ans[index] < ans[j]) ans[j] = ans[index] + e[index][j];}}if(ans[n] == inf) cout<<"-1"<<endl;else cout<<ans[n]<<endl;
}signed main()// Don't forget pre_handle!
{IOSint T=1;
//	cin>>T;while(T--) solve(); return 0;
} 

这里奉上Dijkstra朴素版的模板,ICPCer可拿~【适用于n<=1e3且没有负边权(用SPFA)】 

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f3f3f3f3f;  // 定义无穷大void solve()
{// 输入点数和边数int n,m;cin>>n>>m;// 邻接矩阵存图,初始化为infvector<vector<int>> e(n+1,vector<int>(n+1,inf));// 标记数组,记录是否已确定最短路vector<bool> v(n+1,false);// 存储起点到各点的最短距离vector<int> ans(n+1,inf);// 建图,处理边输入for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u][v]=w;  // 有向图建边// e[v][u]=w; // 如果是无向图需要加上这行}// 初始化,起点距离设为0ans[1]=0;//起点和终点看题目要求// Dijkstra主过程,循环n次for(int i=1;i<=n;i++){int mi=inf;     // 当前未处理节点中的最小距离int index=0;    // 对应的节点编号// 遍历所有节点,找出未处理且距离最小的节点for(int j=1;j<=n;j++){if(!v[j]&&ans[j]<mi){mi=ans[j];index=j;}}// 标记该节点已处理v[index]=true;// 松弛操作:通过该节点更新其他节点的距离for(int j=1;j<=n;j++){if(!v[j]&&e[index][j]+ans[index]<ans[j]){ans[j]=ans[index]+e[index][j];}}}// 输出结果,如果不可达输出-1if(ans[n]==inf) cout<<"-1"<<endl;else cout<<ans[n]<<endl;
}
signed main()
{IOS;int T=1;//cin>>T;while(T--){solve();}return 0;
}

堆优化版Dijkstra

题目重现

堆优化就是利用小顶堆来避免每次都遍历寻找最值,并且用邻接表代替邻接矩阵更能优化第二个for循环,因为邻接表中存的就是这个点之后所连接的点,直接用auto遍历即可,不过需要分清里面的fi和se分别都对应的哪些变量!

参加科学大会:堆优化版代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int N = 520;
vector<vector<pii>> e(N);//邻接表
vector<int> ans(N,inf);//各个点到起点的最近距离
vector<bool> f(N,false);//标记访问数组
priority_queue<pii,vector<pii>,greater<pii>> q;//最小堆优化
int n,m;void solve()
{cin>>n>>m;for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u].push_back({v,w});//用邻接表建图}ans[1] = 0;q.push({ans[1],1});//fi为ans se为索引while(!q.empty()){int mi = q.top().fi;int index = q.top().se;q.pop();if(f[index]) continue;//如果访问过就continue!!!!!f[index] = true;for(auto i : e[index]){//i.fi是点的索引 i.se是边权if(ans[index] + i.se < ans[i.fi]){ans[i.fi] = ans[index] + i.se;q.push({ans[i.fi],i.fi});//别忘记在找到一个点之后就更新ans[i.fi]//在找到更优解的时候再加入队列!!!}}}if(ans[n] == inf) cout<<"-1"<<endl;else cout<<ans[n]<<endl;
}signed main()// Don't forget pre_handle!
{IOSint T=1;
//	cin>>T;while(T--) solve(); return 0;
} 

这里同样奉上堆优化版的模板,ICPCer可拿~

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int N = 520;// Dijkstra堆优化模板(邻接表实现)
// 适用情况:稀疏图,点数较多(mlogn复杂度)
// 功能:求单源最短路,解决非负权图
// 注意:inf需要根据题目调整,避免溢出vector<vector<pii>> e(N);  // 邻接表存图
vector<int> ans(N, inf);   // 存储起点到各点的最短距离
vector<bool> f(N, false);  // 标记是否已确定最短路
priority_queue<pii, vector<pii>, greater<pii>> q;  // 小根堆优化
int n, m;void solve()
{cin >> n >> m;// 邻接表建图for(int i = 1; i <= m; i++){int u, v, w;cin >> u >> v >> w;e[u].push_back({v, w});  // 有向图建边// e[v].push_back({u, w}); // 无向图需要加上这行}// 初始化起点距离ans[1] = 0;q.push({ans[1], 1});  // first存距离,second存节点编号// Dijkstra主过程while(!q.empty()){int mi = q.top().fi;    // 当前最小距离int index = q.top().se; // 对应节点q.pop();// 如果该节点已确定最短距离,跳过if(f[index]) continue;f[index] = true;  // 标记已确定// 遍历所有邻接点for(auto i : e[index]){// i.fi是邻接点索引,i.se是边权if(ans[index] + i.se < ans[i.fi]){ans[i.fi] = ans[index] + i.se;  // 松弛操作q.push({ans[i.fi], i.fi});      // 将新距离加入堆}}}// 输出结果if(ans[n] == inf) cout << "-1" << endl;else cout << ans[n] << endl;
}signed main()
{IOS;int T = 1;//cin >> T;while(T--){solve();}return 0;
}

一定一定要注意访问过就continue!每次的操作(步骤1和3都是对未访问元素的操作!)

接下来就运用一下Dijkstra算法吧!

代价转移

题目链接:代价转移

这道题与众不同的就是没有直接给出图的构造,而是需要不断的动态的更新,不过换汤不换药,不过要注意对于动态生成的节点要判断是否合理,如果不合理的话就应该continue防止导致未定义越界(负节点 或 超大节点)导致死循环!max(a,b) * 2仅仅是合理的范围,不是动态生成的点的范围

下面来看详细代码:

// Problem: 代价转移
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/113664/B
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f3f3f3f3f;void solve()
{int a,b,c1,c2,c3;cin>>a>>b>>c1>>c2>>c3;if(a >= b)//对特殊情况进行判断{cout<<(a - b) * c2 <<endl;return ;}//Dijkstra求最短路:int N = max(a,b) * 2;//先预定一个可达点范围vector<int> ans(N+1,inf);//初始化为最大vector<bool> v(N+1,false);//标记访问数组priority_queue<pii,vector<pii>,greater<pii>> q;//小顶堆ans[a] = 0;//依旧初始化q.push({0,a});//首先将起点入队while(!q.empty()){int value = q.top().fi;//直接找出最小值int index = q.top().se;//q.fi是代价 q.se数q.pop();//将这个点放入最短路径中了(不在非访问的数里面了)if(v[index]) continue;//一定一定别忘记 Dijkstra的核心v[index] = true;//标记已访问pii adj[] = {{index + 1,c1},{index - 1,c2},{index * 2,c3}};//动态生成三个新节点for(auto i : adj)//对三个节点进行遍历{if(i.fi < 1 || i.fi > N) continue;//注意要对新节点的合理性检查 常规图中都是合理点 但是这里是不断动态生成的点 需要检查if(ans[index] + i.se < ans[i.fi])//更新更优解{ans[i.fi] = ans[index] + i.se;q.push({ans[i.fi],i.fi});//在找到满足条件的值之后再入队}}}cout<<ans[b]<<endl;
}signed main()// Don't forget pre_handle!
{IOSint T=1;cin>>T;while(T--) solve(); return 0;
} 

以上内容就是关于Dijkstra算法的两种实现思路了,感兴趣的小伙伴可以收藏起来到整理模版的时候直接食用!

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

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

相关文章

WPFC#超市管理系统(2)顾客管理、供应商管理、用户管理

超市管理系统3. 顾客管理3.1 顾客新增3.2 DataGrid样式3.3 顾客删除3.4 顾客修改4. 供应商管理4.1 供应商管理主界面4.2 新增供应商4.3 修改供应商5. 用户管理5.1 用户管理主界面5.2 新增用户5.3 修改用户总结3. 顾客管理 在CustomerView.xaml使用命令绑定方式添加页面加载Loa…

Windows本地部署DeepSeek

1、Ollama1、下载Ollama安装包https://ollama.com/download&#xff08;如果下载很慢 可以直接找我拿安装包&#xff09;2、使用命令行安装打开cmd 将下载的安装包OllamaSetup.exe 放到想要安装的目录下。&#xff08;如果直接双击&#xff0c;会装到C盘&#xff09;例如想装到…

基于Python的新闻爬虫:实时追踪行业动态

引言 在信息时代&#xff0c;行业动态瞬息万变。金融从业者需要实时了解政策变化&#xff0c;科技公司需要跟踪技术趋势&#xff0c;市场营销人员需要掌握竞品动向。传统的人工信息收集方式效率低下&#xff0c;难以满足实时性需求。Python爬虫技术为解决这一问题提供了高效方…

阿里视频直播解决方案VS(MediaMTX + WebRTC) 流媒体解决方案

背景&#xff1a; 公司采购了新的摄像头&#xff0c;通过rtsp或者rtmp推流到云平台&#xff0c;云平台内部进行转码处理&#xff0c;客户端使用HLS或HTTP-FLV播放&#xff0c;移动App可能使用HLS或私有SDK&#xff0c;超低延时则采用WebRTC。 技术选型&#xff1a; RTSP&…

day33:零基础学嵌入式之网络——TCP并发服务器

一、服务器1.服务器分类单循环服务器&#xff1a;只能处理一个客户端任务的服务器并发服务器&#xff1a;可同时处理多个客户端任务的服务器二、TCP并发服务器的构建1.如何构建&#xff1f;&#xff08;1&#xff09;多进程&#xff08;每一次创建都非常耗时耗空间&#xff0c;…

VR全景制作的流程?VR全景制作可以用在哪些领域?

VR全景制作的流程&#xff1f;VR全景制作可以用在哪些领域&#xff1f;VR全景制作&#xff1a;流程、应用与未来虚拟现实&#xff08;VR&#xff09;全景制作正迅速改变我们的感官体验&#xff0c;使我们能够身临其境地探索虚拟世界&#xff0c;享受沉浸式的奇妙感受。那么&…

用LangChain重构客服系统:腾讯云向量数据库+GPT-4o实战

人们眼中的天才之所以卓越非凡&#xff0c;并非天资超人一等而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。———— 马尔科姆格拉德威尔 目录 一、传统客服系统痛点与重构价值 1.1 传统方案瓶颈分析 1.2 新方案技术突破点 二、系统架构设计&…

主要分布在腹侧海马体(vHPC)CA1区域(vCA1)的混合调谐细胞(mixed-tuning cells)对NLP中的深层语义分析的积极影响和启示

腹侧海马体CA1区&#xff08;vCA1&#xff09;的混合调谐细胞&#xff08;mixed-tuning cells&#xff09;通过整合情感、社会关系、空间概念等多模态信息&#xff0c;形成动态的情景化语义表征&#xff0c;为自然语言处理&#xff08;NLP&#xff09;的深层语义分析提供了重要…

ESP32的ADF详解:6. Audio Processing的API

一、Downmix 1. 核心功能 将基础音频流和新加入音频流混合为单一输出流&#xff0c;支持动态增益控制和状态转换。输出声道数与基础音频一致&#xff0c;新加入音频自动转换声道匹配。2. 关键特性声道处理 输出声道数 基础音频声道数新加入音频自动转换声道&#xff08;如立体…

Qt(基本组件和基本窗口类)

一、基本组件1. Designer设计师为什么要上来先将这个东西呢&#xff0c;这个是QT外置的设计界面的工具&#xff0c;没啥用&#xff0c;所以了解一下。我们用的多的是QT内置的界面设计&#xff0c;只需要我们双击我们创建的项目的.ui文件就可以进入这个界面&#xff0c;你对界面…

docker与k8s的容器数据卷

Docker容器数据卷 特性 docker镜像由多个只读层叠加而成&#xff0c;启动容器时&#xff0c;Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件&#xff0c;那么该文件将会从读写层下面的只读层复制到读写层&#xff0c;该…

自然语言处理技术应用领域深度解析:从理论到实践的全面探索

1. 引言:自然语言处理的技术革命与应用前景 自然语言处理(Natural Language Processing,NLP)作为人工智能领域的核心分支,正在以前所未有的速度改变着我们的数字化生活。从最初的规则基础系统到如今基于深度学习的大语言模型,NLP技术经历了从理论探索到实际应用的深刻变…

OpenGLRender开发记录(二): 阴影(shadowMap,PCF,PCSS)

目录已实现功能阴影shadowMapPCFPCSS实现shadowMapPCFPCSS阴影GitHub主页&#xff1a;https://github.com/sdpyy1 OpenGLRender:https://github.com/sdpyy1/CppLearn/tree/main/OpenGL 已实现功能 除了上次实现IBL之外&#xff0c;项目目前新增了imGUI的渲染&#xff0c;更方便…

Linux:日志乱码

1、Linux日志乱码可能是XShell客户端编码没设置为UTF-8引起的&#xff0c;按照以下步骤&#xff0c;设置终端格式&#xff1a;中文版&#xff1a;打开Xshell会话属性&#xff08;文件→属性→终端→编码&#xff09;&#xff0c;选择与服务器一致的编码格式&#xff08;如UTF-8…

Rouge:面向摘要自动评估的召回导向型指标——原理、演进与应用全景

“以n-gram重叠量化文本生成质量&#xff0c;为摘要评估提供可计算标尺” Rouge&#xff08;Recall-Oriented Understudy for Gisting Evaluation&#xff09; 是由 南加州大学信息科学研究所&#xff08;ISI&#xff09;的Chin-Yew Lin 于2004年提出的自动文本摘要评估指标&am…

[STM32][HAL]stm32wbxx 超声波测距模块实现(HY-SRF05)

前言 在电子技术应用中,距离测量是一个常见且重要的需求。超声波模块因其测量精度较高、成本较低、易于使用等优点,被广泛应用于机器人避障、液位检测、智能停车系统等领域。该文主要讲解以stm32wb芯片为主控,用HAL库来对HY-SRF05超声波模块进行代码编写,实现基本的驱动和测…

MySQL 性能调优实战指南:从诊断到优化全解析

引言在日常的数据库运维工作中&#xff0c;我们经常需要对 MySQL 数据库进行诊断和性能分析。本文将介绍一套全面的 MySQL 诊断脚本&#xff0c;适用于 MySQL 8.0&#xff08;兼容 8.0.15 及以上版本&#xff09;&#xff0c;涵盖事务锁分析、性能瓶颈定位、配置检查、连接状态…

8. 状态模式

目录一、应用背景二、状态模式2.1 解决的问题2.2 角色2.3 实现步骤三、通用设计类图四、实现4.1 设计类图4.2 状态转换图4.3 代码实现一、应用背景 某对象发生变化时&#xff0c;其所能做的操作也随之变化。应用程序的可维护性和重用性差代码的逻辑较复杂 二、状态模式 2.1 …

php语法--foreach和in_array的使用

文章目录foreach基础语法&#xff1a;案例1&#xff1a;引用传递模式&#xff1a;嵌套数组处理&#xff1a;避免在循环中计算数组长度&#xff1a;使用引用减少内存拷贝&#xff1a;打印数组in_array基础使用严格使用foreach 基础语法&#xff1a; foreach ($iterable as $va…

ES6模块详解:核心语法与最佳实践

以下是 EMAScript 6&#xff08;ES6&#xff09;模块规范的核心要点及细节解析&#xff1a; &#x1f4e6; 一、核心语法导出&#xff08;export&#xff09; 命名导出&#xff1a;支持导出多个具名成员。export const a 1; export function b() { /* ... */ } // 或集中导出 …