题目
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 city0
to city2
with 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 city0
to city2
with at most 0 stop costs 500, as marked blue in the picture.
Constraints:
1 <= n <= 100
0 <= flights.length <= (n * (n - 1) / 2)
flights[i].length == 3
0 <= fromi, toi < n
fromi != toi
1 <= pricei <= 104
- There will not be any multiple flights between two cities.
0 <= src, dst, k < n
src != 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<n;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可能极小,成为最终解的一部分