【LeetCode 787】 Cheapest Flights Within K Stops

100 篇文章 0 订阅
88 篇文章 0 订阅

题目描述

There are n cities connected by m flights. Each flight starts from city u and arrives at v with a price w.

Now given all the cities and flights, together with starting city src and the destination dst, your task is to find the cheapest price from src to dst with up to k stops. If there is no such route, output -1.

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

Note:

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.

思路

思路一:动态规划。遍历步数k, 每一步遍历所有路径,对上一步能够更新的点更新。时间复杂度O(K*E) ≈ O(Kn^2)
思路二:深搜 dfs。时间复杂度 O(n^(K+1))。搜索从当前点到目标点的代价。两个剪枝,如果到当前点的代价已经大于当前答案,不需要继续。一次路径中,同一个点没必要访问两次。
思路三:广搜 bfs。和动态规划的思路差不多,以步数来搜索,队列存储上一步到达的所有点以及代价,新的一步,对上一步能到达的点的代价进行更新。时间复杂度和深搜相同。

代码

动态规划

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
        vector<vector<int> > dp(K+2, vector<int>(n, INT_MAX/2));
        dp[0][src] = 0;
        
        for (int k=1; k<=K+1; ++k) {
            dp[k][src] = 0;
            for (int i=0; i<flights.size(); ++i) {
                int a = flights[i][0], b = flights[i][1], p = flights[i][2];
                dp[k][b] = min(dp[k][b], dp[k-1][a]+p);
            }
        }
        
        return dp[K+1][dst] == INT_MAX/2 ? -1 : dp[K+1][dst];
    }
};

BFS

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
        unordered_map<int, vector<pair<int, int>>> mp;
        for (const auto& e : flights) {
            mp[e[0]].emplace_back(e[1], e[2]);
        }
        queue<pair<int, int> > que; // cur, price
        que.push({src, 0});
        int ans = INT_MAX/2;
        int step = 0;
        
        while(!que.empty()) {
            int size = que.size();
            while(size--) {
                int cur = que.front().first;
                int cost = que.front().second;
                que.pop();
                if (cur == dst) {
                    ans = min(ans, cost);
                    continue;
                }
                for (const auto& p : mp[cur]) {
                    if (cost + p.second > ans) continue;
                    que.push({p.first, cost+p.second});
                }
            }
            
            if (++step > K+1) break;
        }
        
        return ans == INT_MAX/2 ? -1 : ans;
    }
};

DFS

class Solution {
public:
    int ans = INT_MAX/2;
    unordered_map<int, vector<pair<int, int>>> mp;
    
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
        for (const auto& e : flights) {
            mp[e[0]].emplace_back(e[1], e[2]);
        }
        vector<int> vis(n, 0);
        vis[src] = 1;
        dfs(src, dst, K, 0, vis);
        return ans == INT_MAX/2 ? -1 : ans;
    }
    
    void dfs(int cur, int dst, int step, int cost, vector<int>& vis) {
        if (cur == dst) {
            ans = cost;
            return;
        }
        if (step < 0) return;
        
        for (const auto& p : mp[cur]) {
            if (cost + p.second > ans) continue;
            if (vis[p.first]) continue;
            vis[p.first] = 1;
            dfs(p.first, dst, step-1, cost+p.second, vis);
            vis[p.first] = 0;
        }
        return;
    }
};

建图的技巧挺好的。
啊啊啊。今天阴天,连带着心情也不是很好。暴躁.jpg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值