[Leetcode] Cheapest Flights Within K Stops 计算最便宜票价

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.node

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:
https://s3-lc-upload.s3.amazo...
The cheapest price from city 0 to city 2 with at most 1 stop costs 200, as marked red in the picture.python

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.app

给定一个数组,其中每一个元素表明着从[出发城市,目的城市,飞机票价],如今再给定任意一对不必定有直飞航线的出发城市和目的城市,和最大容许的中转次数K,求具备最便宜总价的航线组合。this

深度优先搜索

思路

想知道从A到B最便宜的机票组合,只要将全部从A到B在K个中转以内的全部路径组合都遍历一遍,就能找到最低的价格。然而本题的输入是城市之间的航线,因此咱们还要先根据这些航线构建一个航线图。因为题中说明了不会产生环路,也不会有重复的航线,因此在遍历图时不须要检测环路。code

这里须要剪枝减小搜索分叉才能经过OJ,剪枝的要点包括:orm

  1. 经过visited集合,记录当前路径中已经访问过的城市,本条路径中将再也不访问
  2. 若是当前路径的距离已经大于以前发现的最短距离,则不用再继续向下搜索
  3. 中转次数一旦超过也不须要再向下搜索
class GraphNode:
    def __init__(self, name):
        self.name = name
        self.dsts = []
    
    def addFlight(self, dst, price):
        self.dsts.append((dst, price))
        

class Solution:
    def findCheapestPrice(self, n, flights, src, dst, K):
        """
        :type n: int
        :type flights: List[List[int]]
        :type src: int
        :type dst: int
        :type K: int
        :rtype: int
        """
        flightsMap = self.constructGraph(flights)
        self.globalMin = float('inf')
        self.findFlight(flightsMap, flightsMap.get(src), 0, dst, 0, K, set())
        return -1 if self.globalMin == float('inf') else self.globalMin
        
    def findFlight(self, flightsMap, node, totalPrice, finalDst, stops, stopLimit, visited):
        if node is None or stops > stopLimit:
            return
        if self.globalMin < totalPrice:
            return
        for dst in node.dsts:
            dstName, dstPrice = dst
            nextTotalPrice = dstPrice + totalPrice
            if dstName == finalDst: # 若是找到目的地,则计算当前的距离并和最小值比较
                self.globalMin = min(self.globalMin, nextTotalPrice)
            elif flightsMap.get(dstName) is not None and self.globalMin > nextTotalPrice and dstName not in visited: # 若是不是目的地,则继续向下找,这里中转次数要加一,而且本条路径中已经访问过的节点不用再访问
                visited.add(dstName)
                self.findFlight(flightsMap, flightsMap.get(dstName), nextTotalPrice, finalDst, stops + 1, stopLimit, visited)
                visited.remove(dstName)

    def constructGraph(self, flights):
        flightsMap = {}
        for flight in flights: # 将航线按照出发城市一一加入图中
            src = flight[0]
            dst = flight[1]
            price = flight[2]
            node = flightsMap.get(src, GraphNode(src))
            node.addFlight(dst, price)
            flightsMap[src] = node
        return flightsMap
相关文章
相关标签/搜索