目录
注意事项
如果图中存在负权回路,那么不一定存在最短路。因为如果在负权回路里无限循环最后走出来最短路为负无穷。
例如下图
但是我们上面说的是如果存在负权回路,不一定存在最短路。为什么呢?因为只要这个负权回路不在初始点到末尾点的路径上,那这个负权回路对最短路没有影响。
算法实现思路
① 两层循环,第一层循环循环n次,n代表节点的个数。
②第二层循环循环m次,m代表边的条数。每次内层循环比较当前边终点存放的距离和当前边起点存放的距离+这条边长度的关系,如果终点存放的距离大于起点存放的距离+这条边的长度,那么更新终点存放的距离。
如下图所示,就会发生更新。
练习题目:有边数限制的最短路
java题解
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int[][] way = new int[10010][3];// 存放边
static int[] dist = new int[510];// 存放到某点的距离
static int[] last = new int[510];// ***存放上一次循环各点的距离***
static int[] temp = new int[3];// 存放单条边
static int n, m, k;
public static void Bellman_Ford() {
Arrays.fill(dist, 50000);// 初始化
dist[1] = 0;
for (int i = 0; i < k; i++) {
last = Arrays.copyOfRange(dist, 0, dist.length);// 将上一次的结果复制给last
for (int j = 0; j < m; j++) {
temp = way[j];
dist[temp[1]] = Math.min(dist[temp[1]], last[temp[0]] + temp[2]);
}
}
}
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
n = input.nextInt();
m = input.nextInt();
k = input.nextInt();
for (int i = 0; i < m; i++) {
way[i][0] = input.nextInt();
way[i][1] = input.nextInt();
way[i][2] = input.nextInt();
}
Bellman_Ford();
if (dist[n] > 25000)// 存在负权边,不能直接等于
System.out.println("impossible");
else
System.out.println(dist[n]);
}
}