本题要求最多经过 k 个城市的条件下,从城市 src 到城市 dst 的最低运输成本。
在之前的Bellman_ford朴素算法中,我们是对所有边 松弛了 n-1 次,就一定可以得到 从源点出发 总共走n-1条边 到达终点的 最短距离。
那么本题是最多经过k个城市,换句话来说实际上是走了n + 1 条边。
上图所示,从节点1走到节点4 ,经过了两个节点,但是走了三条边。
所以本题可以简化为:起点最多经过 k + 1条边到达终点的最短距离。
在原有的Bellman_ford算法代码基础上松弛k + 1次即可。
但是在松弛k + 1 次过程中,没有体现最多经过 k 个城市 这一附加条件。造成在更新minDist数组时,在同一轮松弛过程中,使用了当前轮次的松弛的minDist结果,但这是不对的。每松弛轮更新的minDist数组是上一轮松弛的minDist的值才可以。
因此每次判断更新minDist数组时,要拿上一轮的minDist数组和当前轮的minDist数组比较才可以
完整代码如下:
import java.util.*;
public class Main{
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
//存储所有的边
List<Edge> edges = new ArrayList<>();
for(int i = 0; i < m; i++){
int s = scanner.nextInt();
int t = scanner.nextInt();
int v = scanner.nextInt();
edges.add(new Edge(s, t, v));
}
int src = scanner.nextInt();
int dst = scanner.nextInt();
int k = scanner.nextInt();
//minDist数组
int[] minDist = new int[n + 1];
for(int i = 0; i < minDist.length; i++){
minDist[i] = Integer.MAX_VALUE;
}
//设置src为源点,所以节点src到源点的距离初始化为0
minDist[src] = 0;
int[] minDistCopy = new int[n + 1];
//对所有边松弛 k + 1次
for(int i = 0; i <= k; i++){
//对minDist进行复制,
//防止在同一轮松弛过程中,更新边的时候用到了当前轮更新过的minDist
minDistCopy = Arrays.copyOf(minDist, n+1);
for(Edge edge : edges){
if(minDistCopy[edge.from] != Integer.MAX_VALUE && minDistCopy[edge.from] + edge.val < minDist[edge.to]){
minDist[edge.to] = minDistCopy[edge.from] + edge.val; }
}
}
if(minDist[dst] == Integer.MAX_VALUE){
System.out.print("unreachable");
}else{
System.out.print(minDist[dst]);
}
}
}
class Edge{
public int from;
public int to;
public int val;
public Edge(int from, int to, int val){
this.from = from;
this.to = to;
this.val = val;
}
}

No responses yet