LeetCode第 787 题:K 站中转内最便宜的航班(C++)

2023-10-18 23:40

本文主要是介绍LeetCode第 787 题:K 站中转内最便宜的航班(C++),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

787. K 站中转内最便宜的航班 - 力扣(LeetCode)
在这里插入图片描述

典型的dijkstra算法,几乎是固定优先级队列加上bfs(bfs求出的都是最大/最小)的思路了,这题多加了一个中转站的限制

不过我还是太年轻,代码并没有通过全部案例,第43个卡住了,主要问题是使用优先级队列的话,跳出循环的条件很难处理,k值和终点哪个作为判断依据暂时不明确。

class Solution {
public:struct cmp{//按照距离排序bool operator()(const pair<pair<int, int>, int> &a, const pair<pair<int, int>, int> &b){return a.first.second < b.first.second;}};int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {vector<int> distance(n, INT_MAX);//记录该节点到起点的距离unordered_map<int, vector<pair<int, int>>> adj;//pair里面的两个元素分别表示顶点编号和距离for(const auto &v : flights)    adj[v[0]].push_back({v[1], v[2]});//构建邻接表//pair<pair<编号,到起点的距离>, 当前层次编号>,当前层次编号是用来记录中转站的priority_queue<pair<pair<int, int>, int>, vector<pair<pair<int, int>, int>>, cmp> q;q.push({{src, 0}, 0});//起点自己到自己的距离为0while(!q.empty()){int cur = q.top().first.first, dis = q.top().first.second;int level = q.top().second;q.pop();if(level > K){break;}//考虑与当前节点cur相连(指向)的节点,并更新起点到他们的距离for(const auto &v : adj[cur]){if(distance[v.first] > dis + v.second){//更新距离distance[v.first] = dis + v.second;q.push({{v.first, distance[v.first]}, 1+level});}}}return distance[dst] == INT_MAX ? -1 : distance[dst];}
};

队列 + bfs

而且上述代码很臃肿,主要是因为使用pair嵌套来传递当前的层次(类似二叉树的层次遍历的思路)。但是层次遍历的时候其实是没有必要专门传递层数的,可以每次在while里面再使用一个for循环处理队列中的全部元素,这样一个while循环就是一层,具体还是看代码:

class Solution {
public:int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {//题目描述说不存在环,所以不用记录顶点是否访问过int res = INT_MAX;unordered_map<int, vector<pair<int, int>>> adj;//pair里面的两个元素分别表示顶点编号和距离for(const auto &v : flights)    adj[v[0]].push_back({v[1], v[2]});//构建邻接表//pair<编号,到起点的距离>queue<pair<int, int>> q;//使用普通队列而不是优先级队列q.push({src, 0});//起点自己到自己的距离为0int step = 0;while(!q.empty() && step <= K){int n = q.size();//事先记录size,一次while循环遍历一个层次for(int i = 0; i < n; ++i){int cur = q.front().first, dis = q.front().second;q.pop();//考虑与当前节点cur相连(指向)的节点,并更新起点到他们的距离for(const auto &v : adj[cur]){if(dis + v.second >= res)   continue;if(v.first == dst)  res = dis+v.second;else q.push({v.first, dis+v.second});}}++step;}return res == INT_MAX ? -1 : res;}
};

所以我还是常常把题目想得太复杂了,拿到题目就像往dijkstra算法上面去套。。。

Bellman-Ford

这个算法目前还不懂,但是看起来真的好厉害。

可以去看这儿的图;最短路径(三)—Bellman-Ford算法(解决负权边)_小地盘的诺克萨斯-CSDN博客

class Solution {
public:int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {vector<int> dp(n, INT_MAX/2);//src到各个位置的最短距离vector<int> backup(n);dp[src] = 0;for(int k = 0; k <= K; ++k){//k次松弛backup.assign(dp.begin(), dp.end());for(const auto &f : flights){//枚举所有的边if(dp[f[1]] > backup[f[0]] + f[2])  dp[f[1]] = backup[f[0]] + f[2];}}return dp[dst] == INT_MAX/2 ? -1 : dp[dst];}
};

可以稍作优化:

class Solution {
public:int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {vector<int> dis(n, INT_MAX/2);//src到各个位置的最短距离vector<int> backup(n);dis[src] = 0;for(int k = 0; k <= K; ++k){//k次松弛backup.assign(dis.begin(), dis.end());for(const auto &f : flights){//枚举所有的边if(dis[f[1]] > backup[f[0]] + f[2])  dis[f[1]] = backup[f[0]] + f[2];}if(backup == dis) break;//这一轮的松弛中每个顶点到起点的距离都没有变化}return dis[dst] == INT_MAX/2 ? -1 : dis[dst];}
};

这篇关于LeetCode第 787 题:K 站中转内最便宜的航班(C++)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/235840

相关文章

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

详解C++中类的大小决定因数

《详解C++中类的大小决定因数》类的大小受多个因素影响,主要包括成员变量、对齐方式、继承关系、虚函数表等,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录1. 非静态数据成员示例:2. 数据对齐(Padding)示例:3. 虚函数(vtable 指针)示例:4. 继承普通继承虚继承5.

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准