旅游省钱大法:加权最短路径 :: labuladong的算法小抄 #1005
Replies: 23 comments 8 replies
-
这里的k的判断其实是有问题的吧?k==0只是代表没有了中转的机会,并不是不可达(还可直接从起点到终点),所以应该将if (k == 0)改为if (k < 0)吧? |
Beta Was this translation helpful? Give feedback.
-
另外其实还有另外一种思路,即倒着过来求,将dp定义为dp(int start, int k),即当前中转次数为k时,从start到dst的最短路径,对应的dp要更改为 // 在中转次数为k的情况下从start到dst的最短路径
public int dp(int start, int k) {
if (start == dst) {
return 0;
}
if (k > this.k) {
return -1;
}
if (memo[start][k] != -666) {
return memo[start][k];
}
int res = Integer.MAX_VALUE;
if (outdegree.containsKey(start)) {
for (int[] element : outdegree.get(start)) {
int to = element[0];
int price = element[1];
int subProblem = dp(to, k + 1);
if (subProblem == -1) continue;
res = Math.min(res, subProblem + price);
}
}
memo[start][k] = res == Integer.MAX_VALUE ? -1 : res;
return memo[start][k];
} 此时也要注意对k的判断 |
Beta Was this translation helpful? Give feedback.
-
@LovesAsuna 嗯, 1、这种边界问题的关键是看题目给的数据边界,题目说了 2、我们在一开始给输入的 |
Beta Was this translation helpful? Give feedback.
-
@LovesAsuna 我上面说的是 是的,这就是我们找到答案的时候,实际上这种情况算法也没有返回 -1,而是返回了 0,因为判断 |
Beta Was this translation helpful? Give feedback.
-
呜呜呜看了这节的题目没看大佬分析,自己尝试自己分析一下,没想到真的写出来了,写的代码有些粗糙劣质~~现在就去完善,谢谢大佬 class Solution {
int[][] memo;
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
memo = new int[n+1][k+2];
return dp(n, flights, src, dst, k+1);
}
public int dp(int n, int[][] flights, int src, int dst, int k){
// base case
if(k < 0){
return -1;
}else if(src == dst){
return 0;
}
if(memo[src][k] != 0){
return memo[src][k];
}
int res = Integer.MAX_VALUE;
for(int[] f : flights){
if(f[0] != src)
continue;
int subProblem = dp(n, flights, f[1], dst, k-1);
if(subProblem == -1){
continue;
}
res = Math.min(res, subProblem + f[2]);
}
memo[src][k] = res==Integer.MAX_VALUE?-1:res;
return memo[src][k];
}
} |
Beta Was this translation helpful? Give feedback.
-
@zzbb9944 千里之行,始于足下,加油! |
Beta Was this translation helpful? Give feedback.
-
这个自底向上的方法 ,比较难想清楚,因为这里的i,j 和之前的dp问题不太一样了,这里的i表示中转次数,比较抽象,且要注意 最后需要对最后一行的结果进行求最小值,不懂的,自己画个二维数组看看。 这个比较抽象,如果看不明白,还是看东哥的解答。 class Solution {
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
int[][] dp = new int[k+1][n];// [i][j] 表示 从 开始节点 到 j节点 中转 i次的最少价格
for(int i = 0; i<k+1;i++){
Arrays.fill(dp[i],10000*101+1);//全部初始化成为 无法取到的值
//这里为什么初始化成这个样子 需要看看题目里面的限制
//但是如果初始化成 MAX_VALUE 是有bug的 会数值溢出 具体什么原因 自己想
}
for(int[] flight: flights){
int from = flight[0];
int to = flight[1];
int cost = flight[2];
if(src == from){
dp[0][to] = cost;
//中转0 次 从 开始节点 到 to这个节点的花费
}
}
//中转 i次
for(int i = 1;i<k+1;i++){
for(int[] flight : flights){
int from = flight[0];
int to = flight[1];
int cost = flight[2];
//从开始节点 中转 i 次 到达 to 需要的最少花费
//在两种中做选择
//从开始处 中转i-1次到达 from(to的前一个节点) 然后 再从前一个节点 到达目标节点位置
//dp[i][to] 有多种方式到达 to ,这个里面 有最小值 也可能有最大值 反正直接比较就完事了
dp[i][to] = Math.min(dp[i][to],dp[i-1][from]+cost);
}
}
int result = 10000*101+1;
//在所有可能中 找到到达 dst 位置的 最小的cost 作为结果
for(int i = 0; i<k+1;i++){
result = Math.min(result,dp[i][dst]);
}
return result == 10000*101+1 ? -1: result;
}
} |
Beta Was this translation helpful? Give feedback.
-
提供一个较粗糙的C++版本的实现,供参考。 class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
//梳理数据结构
vector<vector<int>> graphs(n,vector<int>());
vector<vector<int>> weights(n,vector<int>(n,-1));
for(int i=0;i<flights.size();++i){
graphs[flights[i][1]].emplace_back(flights[i][0]);
weights[flights[i][0]][flights[i][1]]=flights[i][2];
}
//动态规划算法
vector<vector<int>> mem(n,vector<int>(k+1,-1));
int res=dp(src,dst,k,graphs,weights,mem);
return res!=1e9?res:-1;
}
int dp(int from,int to,int k,vector<vector<int>> & graphs,vector<vector<int>>& weights,vector<vector<int>> &mem){
if(from==to) return 0;
if(k<0) return 1e9;
if(mem[to][k]!=-1) return mem[to][k];
int res=1e9;
for(int i=0;i<graphs[to].size();++i){
int candidate=graphs[to][i];
res=std::min(res,dp(from,candidate,k-1,graphs,weights,mem)+weights[candidate][to]);
}
mem[to][k]=res;
return mem[to][k];
}
}; |
Beta Was this translation helpful? Give feedback.
-
Javascript BFS版本: var findCheapestPrice = function(n, flights, src, dst, k) {
// 构建邻接表
const map = new Array(n).fill(0).map((_, i) => ({id: i, edges: []}))
flights.forEach(flight => {
const [from, to, price] = flight
map[from].edges.push({to, price})
})
let res = new Array(n).fill(Number.MAX_SAFE_INTEGER)
let depth = 0; // 记录深度中转站
let q = [] // TODO: 换成优先级队列
q.push([src, 0])
// BFS
while(q.length && depth <= k + 1) {
let len = q.length
while (len) {
const [cur, curPrice] = q.shift()
len--
if (curPrice >= res[cur]) continue
res[cur] = curPrice
for(const edge of map[cur].edges) {
q.push([edge.to, edge.price + curPrice])
}
}
depth++
}
return res[dst] === Number.MAX_SAFE_INTEGER ? -1 : res[dst]
}; |
Beta Was this translation helpful? Give feedback.
-
自己该自己的代码 , 之前的代码感觉写的不够精简, 重构一下 class Solution {
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
// dp[i][j] 表示 经过 j个中转站到达 i 的最低费用
//k+1+1 的原因是 将最后一个节点也理解成中转节点
int[][] dp = new int[n][k+2];
//初始化 , 到达所有节点的初始化为 最大值 , 因为要求最低费用
for(int i = 0 ; i< n ; i++){
Arrays.fill(dp[i],Integer.MAX_VALUE);
}
for(int j = 0; j< k+2 ; j++){
dp[src][j] = 0;//任何src 到src 最小都是 0
}
for(int j = 1; j< k+2 ; j++){
for(int[] flight : flights){
/*
flight[0] form
flight[1] to
flight[2] wight
*/
//这一步防止后面的dp[flight[0]][j-1] + flight[2] 这一步出现 Integer.MAX_VALUE 参加运算 出现 数值溢出现象
//也可以在初始化的时候 初始化成一个较大的数 不一定是Integer.MAX_VALUE
if(dp[flight[0]][j-1] == Integer.MAX_VALUE){
continue;
}
dp[flight[1]][j] = Math.min(dp[flight[1]][j],dp[flight[0]][j-1] + flight[2]);
}
}
return dp[dst][k+1] == Integer.MAX_VALUE ? -1 : dp[dst][k+1];
}
} |
Beta Was this translation helpful? Give feedback.
-
贴个C++解法,状态选的是K和起点而非K和终点(结果相同),用二维数组+pair类型直接构造有向加权图,常规DP class Solution {
vector<vector<int>> memo;
vector<vector<pair<int, int>>> graph;
public:
void buildGraph(vector<vector<int>>& flights, int n) {
graph.assign(n, vector<pair<int, int>>());
for (auto flight: flights) {
int from = flight[0];
int to = flight[1];
int price = flight[2];
graph[from].emplace_back(to, price);
}
}
// 函数返回从src到dst的最多经过K次中转的最便宜价格
int dp(vector<vector<pair<int, int>>>& graph, int src, int dst, int k) {
if (src == dst) return 0; // base case
if (k == -1) return INT_MAX; // 达到中转上限
if (memo[src][k] != -1) return memo[src][k];
int res = INT_MAX;
for (auto neighbor: graph[src]) {
int node = neighbor.first;
int price = neighbor.second;
int subProb = dp(graph, node, dst, k - 1);
if (subProb == INT_MAX) continue;
res = min(res, subProb + price);
}
return memo[src][k] = res;
}
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
buildGraph(flights, n);
memo.assign(n, vector<int> (k + 1, -1));
int res = dp(graph, src, dst, k);
return res == INT_MAX ? -1 : res;
}
}; |
Beta Was this translation helpful? Give feedback.
-
python # 计算每个节点的入度以及对应价格
indegree = {}
for item in flights:
start, to, price = item[0], item[1], item[2]
if to not in indegree:
indegree[to] = []
indegree[to].append([start, price])
k += 1 # k个stop = k+1条边,将中转站个数转化成边的条数
memo = [[-1 for _ in range(k+1)] for __ in range(n)]
# dp定义:从 src 出发,大K 步之内到达 end 的最短路径权重
def dp(end, K):
nonlocal src, indegree, memo
# base case
if end == src:
return 0
if K == 0: # 没有剩余步数了
return -1
if memo[end][K] != -1:
return memo[end][K]
res = float('inf') # 初始化:K步内src到end到最短权重路径
# 只有当end节点有入度时,才是可以到达点路径
if end in indegree:
for sub in indegree[end]:# 分解问题
start, price = sub[0], sub[1]
# 从src到达end前置节点所需的最短路径权重
subProblem = dp(start, K-1)
if subProblem != -1: # 跳过无解问题
res = min(res, subProblem+price)
memo[end][K] = res if res != float('inf') else -1
return memo[end][K]
return dp(dst, k) |
Beta Was this translation helpful? Give feedback.
-
自己做这道题想的是用 i j k 三个状态写的自底向上,做题时想不出更灵巧的状态,用简单的状态去凑,处于超时的边缘: class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
// 存储节点 j 的入边 toedges[j] = [[i0, j, price0], [i1, j, price1], ...]
vector<vector<vector<int>>> toedges(n);
// dp[i][j][k] 表示从 i 到 j 经过 k 次中转的最低价格
vector<vector<vector<int>>> dp(n, vector<vector<int>>(n, vector<int>(k+1, INT_MAX-10000))); // INT_MAX-10000 防止溢出
// base case:
// k == 0 时,最低价格等于直航
for(auto e : flights) {
int i = e[0];
int j = e[1];
int price = e[2];
dp[i][j][0] = price;
toedges[j].push_back(e);
}
for(int kk = 1; kk <= k; kk++) {
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(i == j) continue;
for(vector<int>& e : toedges[j]) {
// 遍历每一条 j 的入边
int prej = e[0];
// 状态转移:
if(prej != i)
dp[i][j][kk] = min(dp[i][j][kk], dp[i][prej][kk-1] + e[2]); // INT_MAX-10000 防止这儿溢出
else
dp[i][j][kk] = min(dp[i][j][kk], dp[i][j][kk-1]);
}
}
}
}
return dp[src][dst][k] == INT_MAX-10000 ? -1 : dp[src][dst][k];
}
}; |
Beta Was this translation helpful? Give feedback.
-
捉个小虫,Dijkstra里,可以通过比较转机次数来保证处理最小cost且最小转机次数 修改后 // 输入一个起点 src,计算从 src 到其他节点的最短距离
int dijkstra(List<int[]>[] graph, int src, int k, int dst) {
// 定义:从起点 src 到达节点 i 的最短路径权重为 distTo[i]
int[] distTo = new int[graph.length];
// 定义:从起点 src 到达节点 i 至少要经过 nodeNumTo[i] 个节点
int[] nodeNumTo = new int[graph.length];
Arrays.fill(distTo, Integer.MAX_VALUE);
Arrays.fill(nodeNumTo, Integer.MAX_VALUE);
// base case
distTo[src] = 0;
nodeNumTo[src] = 0;
// 优先级队列,costFromSrc 较小的排在前面
Queue<State> pq = new PriorityQueue<>((a, b) -> {
if (a.costFromSrc == b.costFromSrc) {
return a.nodeNumFromSrc - b.nodeNumFromSrc;
}
return a.costFromSrc - b.costFromSrc;
});
// 从起点 src 开始进行 BFS
pq.offer(new State(src, 0, 0));
while (!pq.isEmpty()) {
State curState = pq.poll();
int curNodeID = curState.id;
int costFromSrc = curState.costFromSrc;
int curNodeNumFromSrc = curState.nodeNumFromSrc;
if (curNodeID == dst) {
// 找到最短路径
return costFromSrc;
}
if (curNodeNumFromSrc == k) {
// 中转次数耗尽
continue;
}
// 将 curNode 的相邻节点装入队列
for (int[] neighbor : graph[curNodeID]) {
int nextNodeID = neighbor[0];
int costToNextNode = costFromSrc + neighbor[1];
// 中转次数消耗 1
int nextNodeNumFromSrc = curNodeNumFromSrc + 1;
// 剪枝,如果中转次数更多,花费还更大,那必然不会是最短路径
if (costToNextNode > distTo[nextNodeID]
&& nextNodeNumFromSrc > nodeNumTo[nextNodeID]) {
continue;
}
pq.offer(new State(nextNodeID, costToNextNode, nextNodeNumFromSrc));
// 更新 dp table
distTo[nextNodeID] = costToNextNode;
nodeNumTo[nextNodeID] = nextNodeNumFromSrc;
}
}
return -1;
} 原版 // 输入一个起点 src,计算从 src 到其他节点的最短距离
int dijkstra(List<int[]>[] graph, int src, int k, int dst) {
// 定义:从起点 src 到达节点 i 的最短路径权重为 distTo[i]
int[] distTo = new int[graph.length];
// 定义:从起点 src 到达节点 i 至少要经过 nodeNumTo[i] 个节点
int[] nodeNumTo = new int[graph.length];
Arrays.fill(distTo, Integer.MAX_VALUE);
Arrays.fill(nodeNumTo, Integer.MAX_VALUE);
// base case
distTo[src] = 0;
nodeNumTo[src] = 0;
// 优先级队列,costFromSrc 较小的排在前面
Queue<State> pq = new PriorityQueue<>((a, b) -> {
return a.costFromSrc - b.costFromSrc;
});
// 从起点 src 开始进行 BFS
pq.offer(new State(src, 0, 0));
while (!pq.isEmpty()) {
State curState = pq.poll();
int curNodeID = curState.id;
int costFromSrc = curState.costFromSrc;
int curNodeNumFromSrc = curState.nodeNumFromSrc;
if (curNodeID == dst) {
// 找到最短路径
return costFromSrc;
}
if (curNodeNumFromSrc == k) {
// 中转次数耗尽
continue;
}
// 将 curNode 的相邻节点装入队列
for (int[] neighbor : graph[curNodeID]) {
int nextNodeID = neighbor[0];
int costToNextNode = costFromSrc + neighbor[1];
// 中转次数消耗 1
int nextNodeNumFromSrc = curNodeNumFromSrc + 1;
// 更新 dp table
if (distTo[nextNodeID] > costToNextNode) {
distTo[nextNodeID] = costToNextNode;
nodeNumTo[nextNodeID] = nextNodeNumFromSrc;
}
// 剪枝,如果中转次数更多,花费还更大,那必然不会是最短路径
if (costToNextNode > distTo[nextNodeID]
&& nextNodeNumFromSrc > nodeNumTo[nextNodeID]) {
continue;
}
pq.offer(new State(nextNodeID, costToNextNode, nextNodeNumFromSrc));
}
}
return -1;
} |
Beta Was this translation helpful? Give feedback.
-
打卡,打卡。 dp[s, k] 表示k步内从src到达s的最小路径权重. |
Beta Was this translation helpful? Give feedback.
-
dp table c++版本 class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
unordered_map<int, vector<pair<int, int>>> m;
for(auto flight: flights){
int from = flight[0];
int to = flight[1];
int w = flight[2];
if(m.find(to) != m.end()){
m[to].push_back(pair<int, int> (from, w));
}
else{
m[to] = vector<pair<int, int>> (1, pair<int, int> (from, w));
}
}
// dp[i][j]表示中转次数为i时,从src到达城市j的最少花费
vector<vector<int>> dp(k + 1, vector<int> (n, 0));
// base case dp[0][j]
for(int j = 0; j < n; j++){
// 原地不动
if(j == src){
dp[0][j] = 0;
continue;
}
// 找到从src到j的航线
if(m.find(j) != m.end()){
for(auto flight: m[j]){
if(flight.first == src){
dp[0][j] = flight.second;
}
}
// 没有从src到j的航线
if(dp[0][j] == 0) dp[0][j] = -1;
}
else{
// 没有到j的航线
dp[0][j] = -1;
}
}
for(int i = 1; i <= k; i++){
for(int j = 0; j < n; j++){
int res = INT_MAX;
// 原地不动
if(j == src){
dp[i][j] = 0;
continue;
}
// 遍历所有可能航线
for(auto flight: m[j]){
if(dp[i-1][flight.first] == -1) continue;
res = min(res, dp[i-1][flight.first] + flight.second);
}
dp[i][j] = res == INT_MAX ? -1: res;
}
}
return dp[k][dst];
}
}; |
Beta Was this translation helpful? Give feedback.
-
东哥,想问下Dijkstra解法中 nodeNumTo 数组的正确定义。文中你给的定义是 “从起点 src 到达节点 i 至少要经过 nodeNumTo[i] 个节点”,是不是就相当于从src到i的最少节点数。但是我理解 nodeNumTo 数组应该是记录对应distTo[i] 的最短路径要经过的节点数(是不是并不一定是最少节点数呢?),因为侯文nodeNumTo[i] 只有在更新distTo[i]的时候才会同步更新。想问这样的理解正确吗?
|
Beta Was this translation helpful? Give feedback.
-
没人用备忘录的么,刷题小白第一时间想到的是自顶至下搜索 class Solution {
public:
int trace(unordered_map<int, vector<vector<int>>>& dp, int src, int dst, int k/*k为走过的边数*/, vector<vector<int>>& memo){
if(src == dst) return 0;
if(k == 0) return INT_MAX;
if(memo[src][k] != 88888) return memo[src][k];
for(int i=0; i<dp[src].size(); ++i){
int tmp = trace(dp, dp[src][i][0], dst, k-1, memo);
tmp = tmp==INT_MAX ? INT_MAX : tmp+dp[src][i][1];
memo[src][k] = min(memo[src][k], tmp);
}
if(memo[src][k] == 88888) memo[src][k] = INT_MAX;
return memo[src][k];
}
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
unordered_map<int, vector<vector<int>>> dp;
for(int i=0; i<flights.size(); ++i){
dp[flights[i][0]].push_back({flights[i][1], flights[i][2]});
}
vector<vector<int>> memo(n, vector<int>(k+2, 88888));
int res = trace(dp, src, dst, k+1, memo);
return res==INT_MAX ? -1:res;
}
}; |
Beta Was this translation helpful? Give feedback.
-
js 的 dp table 解法,首先将问题中的最多 // 问题等价: 最多 k∈[0,n) 个节点中转等价为最多 k + 1 条边
// dp[i][j] 代表 src 经过 i 条边到达 j 的最小 price
var findCheapestPrice = function (n, flights, src, dst, k) {
const dp = new Array(k + 2).fill(0).map(() => new Array(n).fill(Infinity))
// base case: src 经过任意取值的 j 条边到达 src 的最小 price 均为 0
for (let i = 0; i <= k + 1; i++) dp[i][src] = 0
for (let i = 1; i <= k + 1; i++) {
for (const flight of flights) {
const [from, to, price] = flight
dp[i][to] = Math.min(dp[i][to], dp[i - 1][from] + price)
}
}
return dp[k + 1][dst] === Infinity ? -1 : dp[k + 1][dst]
} |
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
求助大佬们,leetcode 2093. Minimum Cost to Reach City With Discounts和本题比较类似,主要区别在于2093是无向图。想请各位一起讨论一下2093能否用类似本题的dp解法求解? |
Beta Was this translation helpful? Give feedback.
-
787题也可以用Bellman-Ford算法(单源最短路径),维护一个最短路径数组。因为题目中有k个中转的限制,所有需要在Bellman-Ford稍作修改,下面是Java代码实现: class Solution {
/**
* 贝尔曼福特法
* @param n
* @param flights
* @param src
* @param dst
* @param k
* @return
*/
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
final int MAX = Integer.MAX_VALUE/2;// 防止两个MAX相加溢出所以除以二
int[][] graph = new int[n][n];// 邻接矩阵
// 邻接矩阵初始化start
for (int i = 0; i < n;i++){
for(int j = 0; j < n;j++){
if(i==j)graph[i][j]=0;
else graph[i][j] = MAX;
}
}
for(int i = 0; i < flights.length; i++){
int start = flights[i][0];
int end = flights[i][1];
int weight = flights[i][2];
graph[start][end] = weight;
}
// 邻接矩阵初始化end
int[] fpath = new int[n];// 其中存储了src到任意节点的距离
for(int i = 0; i < fpath.length; i++){
fpath[i] = MAX; // 初始化到其他节点为MAX
}
fpath[src] = 0;// src到src的距离为0
// Bellman-Ford算法开始,不断优化fpath这个一维数组
for(int i = 1; i <= k+1; i++){// 如果题目中不限制k,则i<=点数-1
// 复制上一次的迭代结果
int[] clone = fpath.clone();// 使得当前次寻找只在上一次结果的基础上,只能找到经过i条边的最短路径,从而是k+1发挥作用
for(int f= 0; f < flights.length; f++){// 遍历所有边(也可以遍历graph邻接矩阵中存储的每条边)
int start = flights[f][0];
int end = flights[f][1];
int weight = flights[f][2];
fpath[end] = Math.min(fpath[end],clone[start]+weight);// 如果题目中不限制k,则无须用clone 直接用fpath即可
}
}
return fpath[dst]>=MAX ? -1:fpath[dst];
}
} |
Beta Was this translation helpful? Give feedback.
-
哈希分组+备忘录递归 class Solution {
int[][] memo;
Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
memo = new int[n + 1][k + 1];
for (int i = 0; i < flights.length; i++) {
int f = flights[i][0];
int t = flights[i][1];
int p = flights[i][2];
map.putIfAbsent(f, new HashMap<>());
map.get(f).put(t, p);
}
for (int[] a : memo) {
Arrays.fill(a, -2);
}
return dp(flights, src, dst, k);
}
public int dp(int[][] flights, int src, int dst, int k) {
if (k < 0) {
return src == dst ? 0 : -1;
}
//如果等于dst直接返回
if (src == dst) {
return 0;
}
if (memo[src][k] != -2) {
return memo[src][k];
}
//是否包含直达的路径
Map<Integer, Integer> path = map.get(src);
//不可达
if (path == null) return -1;
int min = Integer.MAX_VALUE;
for (Map.Entry<Integer, Integer> entry : path.entrySet()) {
int key = entry.getKey();
int val = entry.getValue();
int res = dp(flights, key, dst, k - 1);
if (res >= 0) {
min = Math.min(min, res + val);
}
}
min = min == Integer.MAX_VALUE ? -1 : min;
memo[src][k] = min;
return min;
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:旅游省钱大法:加权最短路径
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions