LeetCode算法题——Cheapest Flights Within K stops

题目概述

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

Now given all the cities and fights, 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.

Example1

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:

《LeetCode算法题——Cheapest Flights Within K stops》 temp1.png

The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as marked red in the picture.

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:

《LeetCode算法题——Cheapest Flights Within K stops》 temp2.png

The cheapest price from city 0 to city 2 with at most 0 stop costs 500, as marked blue in the picture.

分析

此题考察图论知识,本质上为单源最短路径问题,这种问题可以优先使用Bellman-Ford方法解决:

int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
      vector<int> dist(n, 1e8); // 初始距离设定为很大
        dist[src] = 0;

        for (int i = 0; i <= K; i++) { // 最多K次中继
            vector<int> temp(dist); // 需要引入临时数组记录中间变化
            for (auto edge : flights) // Bellman-Ford
                dist[edge[1]] = min(dist[edge[1]] , dist[edge[0]] + edge[2]);
            dist = temp;
        }
        return dist[dst] == 1e8 ? -1 : dist[dst];
    }

当然,以上思想还可以写成动态规划方法的形式,会更加容易理解。为此,我们需要构造一个二维数组ans,其中的任意一个元素[i][j]表示从起点在j步之内到达结点i的最短路径长度。于是可以得到:

K++;
        vector<vector<int>> ans(n, vector<int>(K+1));
        for (int i = 0; i < n; i++)
            for (int j = 0; j <= K; j++)
                ans[i][j] = 1e8; // 数组初始化

        ans[src][0] = 0;
        for (int i = 1; i <= K; i++) {
            for (int j = 0; j < n; j++)   // 从j-1步的情况中拷贝当前最短路径
                ans[j][i] = ans[j][i-1];
            for (const vector<int>& f: flights) // Bellman-Ford
                ans[f[1]][i] = min(ans[f[1]][i], ans[f[0]][i-1] + f[2]);
        }
        return (ans[dst][K] == 1e8) ? -1 : ans[dst][K];

总结

· 最短路径问题,常见的解决算法有两种,一为Dijsktra,一为Bellman-Ford。对于单源路径问题,采用后者更加直观,但该算法效率较低,时间复杂度达到了O(V*E)级别
· 使用Bellman-Ford进行迭代更新时需要注意,赋值时参与比较的是上一步达到的最短路径加上新路径的和,为此需要引入临时数组拷贝上一次的最短路径,否则会出现错误。

    原文作者:颜ly
    原文地址: https://www.jianshu.com/p/c12c1848c887
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞