有 n 个城市通过 m 个航班连接。每个航班都从城市 u 开始,以价格 w 抵达 v。
现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到从 src 到 dst 最多经过 k 站中转的最便宜的价格。 如果没有这样的路线,则输出 -1。
示例 1:
输入:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
输出: 200
解释:
城市航班图如下
从城市 0 到城市 2 在 1 站中转以内的最便宜价格是 200,如图中红色所示。
示例 2:
输入:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 0
输出: 500
解释:
城市航班图如下
从城市 0 到城市 2 在 0 站中转以内的最便宜价格是 500,如图中蓝色所示。
提示:
n 范围是 [1, 100],城市标签从 0 到 n - 1.
航班数量范围是 [0, n * (n - 1) / 2].
每个航班的格式 (src, dst, price).
每个航班的价格范围是 [1, 10000].
k 范围是 [0, n - 1].
航班没有重复,且不存在环路
思路:Dijkstra最短路变形题,多加一维用来存储中间经过了多少中转站。
class Solution {
class node{
int v,val;
public node(int v,int val) {
this.v=v;
this.val=val;
}
}
class node1{
int id,num,val;
public node1(int id,int num,int val) {
this.id=id;
this.num=num;
this.val=val;
}
}
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
int ans=Integer.MAX_VALUE;
int[][] dis=new int[n][K+1];
Queue<node1> q=new LinkedList<>();
Map<Integer,List<node>> road=new HashMap<>();
for(int i=0;i<flights.length;i++) {
if(!road.containsKey(flights[i][0]))
road.put(flights[i][0], new ArrayList<>());
road.get(flights[i][0]).add(new node(flights[i][1],flights[i][2]));
}
for(int i=0;i<n;i++)
for(int j=0;j<=K;j++)
dis[i][j]=Integer.MAX_VALUE-20000;
q.add(new node1(src,0,0));
dis[src][0]=0;
while(!q.isEmpty()) {
node1 now=q.poll();
//System.out.println(now.id);
if(now.id==dst || !road.containsKey(now.id))
continue;
//System.out.println(now.val);
for(int i=0;i<road.get(now.id).size();i++) {
int index=road.get(now.id).get(i).v;
int weight=road.get(now.id).get(i).val;
int num=(index==dst?now.num:now.num+1);
if(num>K) continue;
if(dis[index][num]>dis[now.id][now.num]+weight) {
dis[index][num]=dis[now.id][now.num]+weight;
q.add(new node1(index,num,dis[index][num]));
}
}
}
for(int i=0;i<=K;i++)
ans=Math.min(ans, dis[dst][i]);
return ans==Integer.MAX_VALUE-20000?-1:ans;
}
}