当前位置: 首页 > news >正文

Dijkstra解决单源最短路径

题目链接:

9.蓝桥王国 - 蓝桥云课https://www.lanqiao.cn/problems/1122/learning/?problem_list_id=30&page=1

题目描述:

        小明是蓝桥王国的王子,今天是他登基之日。在即将成为国王之前,老国王给他出了道题,他想要考验小明是否有能力管理国家。

题目的内容如下:

        蓝桥王国一共有 N 个建筑和 M 条单向道路,每条道路都连接着两个建筑,每个建筑都有自己编号,分别为 1∼N (其中皇宫的编号为 1)。国王想让小明回答从皇宫到每个建筑的最短路径是多少,但紧张的小明此时已经无法思考,请你编写程序帮助小明回答国王的考核。

输入描述:

        输入第一行包含三个正整数 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

解题思路:

         Dijkstra:先设置一个邻接二维数组(如果太大就设置为邻接表),邻接表定义如下:

typedef pair<int,long long> PLI;   //定义节点类型
//创建邻接表
vector<vector<PLI>> adj(N + 1);
for (int i = 0;i < M;i++)
{
	int u, v, w;
	cin >> u >> v >> w;
	adj[u].push_back({ v, w });
}

其创建了一个vector容器,每个vector容器包含一个类型变量为PLI的vector容器,外层容器定义为起点为i,内层容器(j,k)为终点为j,i和j的距离为k的节点,再定义一个小根堆队列,定义如下:

#include<queue>
//定义一个优先队列,最顶上为最小值
priority_queue<PLI, vector<PLI>, greater<PLI>> pq;

当选中距离源点最近的点v后,将点v的邻接边都进行判断,如果(源-v的距离+v-新节点的距离)<(源点-新节点的距离),则将新节点在dist上存储的距离更新,并将新的PLI加入到pq队列中,其代码如下:

while (!pq.empty()) 
{
	int ed = pq.top().first;    //终点
	long long d = pq.top().second;     //距离
	pq.pop();    //退出dist中最小的节点

	//更新ed节点的邻接节点
	for(int i=0;i<adj[ed].size();i++)
	{
		if ((dist[ed] + adj[ed][i].second) < dist[adj[ed][i].first])   //起点到ed的距离+ed到v的距离<原本dist[v]的距离
		{
			dist[adj[ed][i].first] = dist[ed] + adj[ed][i].second;   //更新dist
			pq.push({ adj[ed][i].first ,dist[adj[ed][i].first] });
		}
	}
}

最终就可以得到完整的Dijkstra代码。 

 代码:

1、Dijkstra代码
//Dijkstra
void Dijkstra(vector<vector<PLI>> adj)
{
	//初始化dist数组
	dist[1] = 0;

	//定义一个优先队列,最顶上为最小值
	priority_queue<PLI, vector<PLI>, greater<PLI>> pq;
	pq.push({ 1,0 });   //将起点距离设置为0
	while (!pq.empty()) 
	{
		int ed = pq.top().first;    //终点
		long long d = pq.top().second;     //距离
		pq.pop();    //退出dist中最小的节点

		//更新ed节点的邻接节点
		for(int i=0;i<adj[ed].size();i++)
		{
			if ((dist[ed] + adj[ed][i].second) < dist[adj[ed][i].first])   //起点到ed的距离+ed到v的距离<原本dist[v]的距离
			{
				dist[adj[ed][i].first] = dist[ed] + adj[ed][i].second;   //更新dist
				pq.push({ adj[ed][i].first ,dist[adj[ed][i].first] });
			}
		}
	}
}
2、完整代码
#include<iostream>
#include<vector>
#include<queue>
#include <climits>
#define MAX LLONG_MAX
using namespace std;
typedef pair<int,long long> PLI;   //定义节点类型
vector<long long> dist(300010, MAX);    //起点距离其余个点的距离

//Dijkstra
void Dijkstra(vector<vector<PLI>> adj)
{
	//初始化dist数组
	dist[1] = 0;

	//定义一个优先队列,最顶上为最小值
	priority_queue<PLI, vector<PLI>, greater<PLI>> pq;
	pq.push({ 1,0 });   //将起点距离设置为0
	while (!pq.empty()) 
	{
		int ed = pq.top().first;    //终点
		long long d = pq.top().second;     //距离
		pq.pop();    //退出dist中最小的节点

		//更新ed节点的邻接节点
		for(int i=0;i<adj[ed].size();i++)
		{
			if ((dist[ed] + adj[ed][i].second) < dist[adj[ed][i].first])   //起点到ed的距离+ed到v的距离<原本dist[v]的距离
			{
				dist[adj[ed][i].first] = dist[ed] + adj[ed][i].second;   //更新dist
				pq.push({ adj[ed][i].first ,dist[adj[ed][i].first] });
			}
		}
	}
}

int main()
{
	// 请在此输入您的代码
	//输入
	int N, M;
	cin >> N >> M;

	//创建邻接表
	vector<vector<PLI>> adj(N + 1);
	for (int i = 0;i < M;i++)
	{
		int u, v, w;
		cin >> u >> v >> w;
		adj[u].push_back({ v, w });
	}

	//更新dist数组
	Dijkstra(adj);

	//输出
	for (int i = 1;i <= N;i++)
	{
		i != N ? (dist[i] != MAX ? cout << dist[i] << " " : cout << "-1" << " ") : (dist[i] != MAX ? cout << dist[i] << endl : cout << "-1" << endl);
	}
	return 0;
}

注意:

        ① 测试点2、4:在设置最大距离MAX的时候,为了防止溢出,需要将MAX设置为LLONG_MAX,其包含在头文件<climits>中;

        ②测试点3:需要将不可到达点输出为-1。

相关文章:

  • 2.1 transformer模型原理及代码(python)
  • 深度学习常用操作笔记
  • 多重背包讲解
  • 使用TensorFlow时需掌握的Pandas核心知识点
  • JDK15开始偏向锁不再默认开启
  • Qt开发——问界M9空调
  • 强化学习的一些概念
  • 运维面试题(三)
  • Java虚拟机面试题:内存管理(中)
  • 【java】集合练习2
  • Chapter 4-11. Troubleshooting Congestion in Fibre Channel Fabrics
  • Nest系列:在 NestJS 中使用 Joi 进行环境变量验证与配置管理-03
  • Navicat如何查看密码
  • Chrome 浏览器的很多扩展不能用了
  • 数字签名与非对称加密的区别
  • LLM论文笔记 24: A Theory for Length Generalization in Learning to Reason
  • AJAX PHP:深入理解与实际应用
  • 【WEB APIs】DOM-节点操作
  • 本地部署Deep Seek-R1,搭建个人知识库——笔记
  • Spring Boot使用线程池创建多线程
  • 前列腺癌真的难以早发现吗?如何治疗?专家回应
  • 再囤三个月库存!美国客户抢付尾款,外贸企业发货订单排到7月
  • 证监会副主席李明:近期将出台深化科创板、创业板改革政策措施
  • 芬兰西南部两架直升机相撞坠毁,第一批救援队已抵达现场
  • 当“小铁人”遇上青浦,看00后如何玩转长三角铁三
  • 俄乌直接谈判结束