//787. K 站中转内最便宜的航班
var findCheapestPrice = function (n, flights, src, dst, K) {
//把出和入存到map
//key为dst,value为[src, cost]
const innerMap = new Map();
//key为src,value为[dst,cost]
const outerMap = new Map();
flights.forEach((item) => {
const [src, dst, cost] = item;
if (!innerMap.has(dst)) {
innerMap.set(dst, [[src, cost]]);
} else {
innerMap.get(dst).push([src, cost]);
}
if (K !== 0) {
if (!outerMap.has(src)) {
outerMap.set(src, [[dst, cost]]);
} else {
outerMap.get(src).push([dst, cost]);
}
}
});
let minCost = -1;
if (innerMap.has(dst)) {
innerMap.get(dst).forEach((item) => {
if (item[0] === src) {
if (minCost === -1 || minCost > item[1]) minCost = item[1];
}
});
if (K === 0) return minCost;
} else {
if (K === 0) return -1;
}
let stepCount = K + 1;
//存储当前往前遍历到的结点
let srcMap = new Map();
//起点向前走了一步
if (outerMap.has(src)) {
outerMap.get(src).forEach((item) => {
srcMap.set(item[0], item[1]);
});
} else {
return -1;
}
stepCount--;
while (stepCount !== 0) {
//暂存当前遍历到的结点
let tmpSrcMap = new Map();
srcMap.forEach((cost, src) => {
if (outerMap.has(src)) {
//往前一步
outerMap.get(src).forEach((item) => {
//如果下一步有终点,判断一下价格,比当前最便宜的贵可以剪枝
if (item[0] === dst) {
if (minCost === -1 || item[1] + cost < minCost) {
minCost = item[1] + cost;
}
} else {
//如果路径价格已经高于当前已得出的最便宜的价格,剪枝
if (minCost !== -1) {
if (item[1] + cost < minCost) {
if (tmpSrcMap.has(item[0])) {
if (tmpSrcMap.get(item[0]) > item[1] + cost) {
tmpSrcMap.set(item[0], item[1] + cost);
}
} else {
tmpSrcMap.set(item[0], item[1] + cost);
}
}
} else {
//注意暂存map中如果已有下一步,判断一下两次得到的价格高低,存较小者
if (tmpSrcMap.has(item[0])) {
if (tmpSrcMap.get(item[0]) > item[1] + cost) {
tmpSrcMap.set(item[0], item[1] + cost);
}
} else {
tmpSrcMap.set(item[0], item[1] + cost);
}
}
}
});
}
});
//如果下一步已经没有航班了,跳出循环
if (tmpSrcMap.size === 0) {
break;
}
srcMap = tmpSrcMap;
stepCount--;
}
return minCost;
};