描述
在一个有 nn 个点, mm 个边的有向图中,已知每条边长,求出 11 到 nn 的最短路径,返回 11 到 nn 的最短路径值。如果 11 无法到 nn ,输出 -1−1 图中可能有重边,无自环。
普通迪杰斯特拉(Dijkstra)算法解法
- 基本思想:所有点分为两个集合S和U,以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止
- 实现步骤如下:
- 计算起始节点到U中每一个节点的路径长度,选择其中路径最短的点加入S。
- 借助上一步刚加入S的点,更新U中每个点到S的距离。
- 重复步骤1,2,直到所有的点都加入到S当中。
- 整个过程需要一个二维数组来明确每个点到其他点的距离。
- 二维数组的每个元素需要初始化为
Integer.MAX_VALUE
,方便寻找最短路径 - 需要一个一维数组来区分这个点是在S当中还是U当中。
- 也有人专门建了一个一维数组,用来标记其他点到起始点的最短距离,我选择重复利用上面已经建立的二维数组。
- 可以使用小顶堆减少一次循环,降低时间复杂度。
看不懂了可以参考这几篇博客:
Dijkstra算法(一)之 C语言详解
dijkstra算法求单源最短路径 java版本
import java.util.*;
public class Solution {
public int findShortestPath (int n, int m, int[][] graph) {
boolean[] flag = new boolean[n];
flag[0] = true;
int[][] dis = new int[n][n];
//二维数组不可以使用Arrays.fill赋值。
//Arrays.fill(dis,-1);
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
dis[i][j] = Integer.MAX_VALUE;
}
}
for(int i = 0; i < m; i++){
int a = graph[i][0]-1;
int b = graph[i][1]-1;
int c = graph[i][2];
dis[a][b] = Math.min(dis[a][b],c);//取最小值防止有重边
//dis[b][a] = Math.min(dis[b][a],c);添上这行代码不能ac,不明白为什么?
}
for(int i = 1; i < n; i++){
int min = Integer.MAX_VALUE;
int k = -1;
for(int j = 0; j < n; j++){
if(flag[j] == false && dis[0][j] < min){
min = dis[0][j];
k = j;
}
}
if(k == -1){
break;
}
flag[k] = true;
for(int j = 0; j < n; j++){
//判断dis[k][j] != Integer.MAX_VALUE是为了防止int temp = min + dis[k][j]越界
if(flag[j] == false && dis[k][j] != Integer.MAX_VALUE){
int temp = min + dis[k][j];
dis[0][j] = Math.min(dis[0][j],temp);
}
}
}
if(dis[0][n-1] == Integer.MAX_VALUE){
return -1;
}
return dis[0][n-1];
}
}