[Leetcode 787]中转K站内最便宜机票
题目
n个城市,想求从src到dist的最廉价机票
有中转站数K的限制,即如果k=5,中转10次机票1000,中转5次机票2000,最后返回2000
There are n cities connected by some number of flights. You are given an array flights where flights[i] = [fromi, toi, pricei] indicates that there is a flight from city fromi to city toi with cost pricei.
You are also given three integers src, dst, and k, return the cheapest price from src to dst with at most k stops. If there is no such route, return -1.
Example 1:

Input: n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 1 Output: 200 Explanation: The graph is shown. The cheapest price from city0to city2with at most 1 stop costs 200, as marked red in the picture.
Example 2:

Input: n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 0 Output: 500 Explanation: The graph is shown. The cheapest price from city0to city2with at most 0 stop costs 500, as marked blue in the picture.
Constraints:
1 <= n <= 1000 <= flights.length <= (n * (n - 1) / 2)flights[i].length == 30 <= fromi, toi < nfromi != toi1 <= pricei <= 104- There will not be any multiple flights between two cities.
0 <= src, dst, k < nsrc != dst
思路
和https://www.cnblogs.com/inku/p/15622556.html类似
这题多了一个stepCheck,check中转的次数
dijsktra+优先队列
代码
class Solution { public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) { int[][] adj=new int[n][n]; for(int[] flight_line:flights){ //flighr_line: {from,to,money} adj[flight_line[0]][flight_line[1]]=flight_line[2]; } int[] cost=new int[n]; int[] stepCheck=new int[n]; Arrays.fill(cost,Integer.MAX_VALUE); Arrays.fill(stepCheck,Integer.MAX_VALUE); cost[src] = 0; stepCheck[src] = 0; //int[] cur position,cost,stops PriorityQueue<int[]> pq=new PriorityQueue<>(new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[1]-o2[1]; } }); //pq.add(new int[]{0,0,1}); 错误! pq.offer(new int[]{src, 0, 0});//起点不一定是0,本身不算中转 while (!pq.isEmpty()){ int[] curPos=pq.poll(); int curNode=curPos[0]; int curCost=curPos[1]; int curStop=curPos[2]; if(curNode==dst) return curCost; if(curStop==k+1) continue; for(int i=0;i){ //两地有机票 if(adj[curNode][i]>0){ int cost_try=adj[curNode][i]+curCost; if(cost_try<cost[i]){ cost[i]=cost_try; pq.offer(new int[]{i,cost_try,curStop+1});//便宜的情况,加入 } else if(curStop<stepCheck[i]){ pq.offer(new int[]{i,cost_try,curStop+1});//没便宜,但站数更少的情况,也加入 } stepCheck[i]=curStop;//本身不算stop } } } return cost[dst]==Integer.MAX_VALUE?-1:cost[dst]; } }
疑问
else if(curStop<stepCheck[i]){ pq.offer(new int[]{i,cost_try,curStop+1});//没便宜,但站数更少的情况,也加入 }
没便宜(cost更多),但站数更少的情况下虽然加入了,但因优先队列是按cost排序,那岂不是永远取不到?它的意义?
A:取得到,先加进去再说。虽然当前cost多,但后面的cost可能极小,成为最终解的一部分