zoukankan      html  css  js  c++  java
  • 787. Cheapest Flights Within K Stops

    问题:

    给定n个地点,以及地点之间的航班和费用。

    求从src到dst,中转最多k次以内,花费最少的费用。

    Example 1:
    Input: 
    n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
    src = 0, dst = 2, k = 1
    Output: 200
    Explanation: 
    The graph looks like this:
    The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as marked red in the picture.
    
    Example 2:
    Input: 
    n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
    src = 0, dst = 2, k = 0
    Output: 500
    Explanation: 
    The graph looks like this:
    The cheapest price from city 0 to city 2 with at most 0 stop costs 500, as marked blue in the picture.
     
    
    Constraints:
    The number of nodes n will be in range [1, 100], with nodes labeled from 0 to n - 1.
    The size of flights will be in range [0, n * (n - 1) / 2].
    The format of each flight will be (src, dst, price).
    The price of each flight will be in the range [1, 10000].
    k is in the range of [0, n - 1].
    There will not be any duplicated flights or self cycles.
    

      

    example 1:

    example 2:

    解法一:BFS

    将从src到node i的cost存入queue。

    {node i, cost}

    由于题目限制中转站点数 k

    因此需要对queue的遍历,通过层次区分。

    ⚠️ 注意:在层次区分的问题中,不能使用优先队列 priority_queue,由于其会打乱节点的层次顺序。

    使用dist数组保存,src到每个节点的最小距离。

    在 k 层以内,按层,随时更新该距离 为最小。

    ⚠️ 注意:queue的遍历,不能因为遍历到dst节点就停止,由于之后还可能存在花费更少的路径,只是中转需要更多的情况。

    因此到达 k 层遍历之前,要一直遍历queue,直到queue遍历结束。

    若dist[dst]==INT_MAX, 则没有src->dst的路径。返回-1,否则返回dist[dst]

    代码参考:

     1 class Solution {
     2 public:
     3     int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
     4         int res=-1;
     5         if(src==dst) return 0;
     6         vector<vector<vector<int>>> graph(n,vector<vector<int>>());
     7         for(vector<int>& flt:flights) {
     8             graph[flt[0]].push_back({flt[1],flt[2]});
     9             //printf("graph[%d]_insert:{%d,%d}
    ", flt[0], flt[1], flt[2]);
    10         }
    11         queue<pair<int,int>> q;//stop, cost
    12         vector<int> dist(n, INT_MAX);
    13         q.push({0,src});
    14         dist[src] = 0;
    15         int cur_s, cur_cost;
    16         int count = 0;
    17         while(!q.empty()) {
    18             int sz = q.size();
    19             for(int i=0; i<sz; i++) {
    20                 cur_cost = q.front().first;
    21                 cur_s = q.front().second;
    22                 q.pop();
    23                 //until k steps, can't return. 
    24                 //cause there maybe a less cost way which may spend more steps.
    25                 //if(cur_s==dst) return min(dist[dst], cur_cost);
    26                 //printf("cur_s:%d cur_cost:%d
    ", cur_s, cur_cost);
    27                 for(auto next:graph[cur_s]) {
    28                     //printf("graph[%d] ", cur_s);
    29                     //printf("next[0]:%d, next[1]:%d
    ", next[0], next[1]);
    30                     if(dist[next[0]] > cur_cost+next[1]) {
    31                         //printf("INSERT next[0]:%d, cur_cost+next[1]:%d+%d
    ", next[0], cur_cost,next[1]);
    32                         dist[next[0]] = cur_cost+next[1];
    33                         q.push({dist[next[0]], next[0]});
    34                     }
    35                 }
    36             }
    37             if(count>=K) return dist[dst]==INT_MAX?-1:dist[dst];
    38             //printf("count:%d
    
    ", count);
    39             count++;
    40         }
    41         return dist[dst]==INT_MAX?-1:dist[dst];
    42     }
    43 };

    解法二:优先队列 priority_queue

    上述解法中,解释了层级相关的问题,不能使用优先队列,

    但如果将层级关系作为变量,保存至queue中,在K以内的所有情况,cost的更新(选取最短距离)都是不限于层级关系的,

    满足K以内的情况,才保存在queue中进行处理,即可规避该问题。

    使用了优先队列,那么可保证先处理的一定是距离最短的节点,

    若先找到dst,即可返回。

    代码参考:

     1 typedef tuple<int, int, int> ti;
     2 class Solution {
     3 public:
     4     int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
     5         if(src==dst) return 0;
     6         vector<vector<vector<int>>> graph(n);
     7         for(vector<int>& flt:flights) {
     8             graph[flt[0]].push_back({flt[1],flt[2]});
     9         }
    10         priority_queue<ti, vector<ti>, greater<ti>> q;//cost,stop,K(level)
    11         q.push({0,src, K+1});
    12         int cur_s, cur_cost, cur_k;
    13         while(!q.empty()) {
    14             auto [cur_cost, cur_s, cur_k] = q.top();
    15             q.pop();
    16             if(cur_s==dst) return cur_cost;
    17             if(!cur_k) continue;//level > K, invalid route
    18             for(auto next:graph[cur_s]) {
    19                 q.push({cur_cost+next[1], next[0], cur_k-1});
    20             }
    21         }
    22         return -1;
    23     }
    24 };
  • 相关阅读:
    Vue和React组件diff更新影响范围对比
    ES6中import和CommonJS中require的区别
    MutationObserver监听DOM变化
    Mint UI中文官网
    为什么在浏览器不支持H265视频播放
    Google谷歌官网首页涂鸦记录
    windows键盘输入无效,键盘灯亮,打字不出字
    javascript实现跨域的方法汇总
    javascript中setInterval的用法
    浅谈Javascript数组的使用
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/14493954.html
Copyright © 2011-2022 走看看