AcWing 849. Dijkstra求最短路 I---java 写法 0.0
原题链接
简单
作者:
lkm
,
2020-09-02 22:40:47
,
所有人可见
,
阅读 1639
import java.util.Arrays;
import java.util.Scanner;
/*
给定一个n个点m条边的 有向图 ,图中可能存在重边和自环,所有边权均为正值。
请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。
输入格式
第一行包含整数n和m。
接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。
输出格式
输出一个整数,表示1号点到n号点的最短距离。
如果路径不存在,则输出-1。
数据范围
1≤n≤500,
1≤m≤10^5,
图中涉及边长均不超过10000。
输入样例:
3 3
1 2 2
2 3 1
1 3 4
输出样例:
3
*/
public class Main {
//从这里看,边是比较多的,所有可以用邻接矩阵存数据
static int N = 510;
static int m, n;
static int[][] g = new int[N][N];
static int[] dist = new int[N];
static boolean[] st = new boolean[N];
//注意:有向图和无向图相比,无向图可以看出有向图
//如果有重边,保留距离最短的那条边
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); m = sc.nextInt();
for (int i = 1; i <= n; i++) Arrays.fill(g[i], 0x3f3f); //权值不超过10000
while (m-- > 0) {
int a = sc.nextInt(), b = sc.nextInt(), c = sc.nextInt();
g[a][b] = Math.min(g[a][b], c);
}
// 表示1号点到n号点的最短距离
System.out.println(dijkstra());
}
private static int dijkstra() {
Arrays.fill(dist, 0x3f3f);
dist[1] = 0; //把自己的距离设置为 0
//遍历一遍 找到一个最小的点,加入到集合中,这里加入到集合里,是通过st来做
//迭代n次,n次迭代后获得最终结果集
for (int i = 0; i < n; i++) {
int t = -1; //表示还没有最短的点
for (int j = 1; j <= n; j++) {
if (!st[j] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
} //循环后找到了最短的点,为 t
st[t] = true; // t 加进结果集中
//最后拿 t 更新一下结果集
for (int j = 1; j <= n; j++) dist[j] = Math.min(dist[j], dist[t] + g[t][j]);
}
if (dist[n] == 0x3f3f) return -1;
else return dist[n];
}
}
大佬你好,不知道你还能不能看到,我先问问为什么初始化 g 数组的时候,全部赋值Integer.MaxValue;会出错,就是int溢出的错误,麻烦解下疑惑,因为这个权值10000,题目中也并没说明
虽然我不是作者,但是我觉得是这样的,因为在后面更新从源点到结点j的时候需要以t结点作为中间结点,也就是说在取两者最小值的时候会进行dist[t] + g[t][j],如果此时结点t到结点j无边的话(也就是Integer.MAX_VALUE)进行相加操作会出现溢出,办法就是在dist[j] = Math.min(dist[j], dist[t] + g[t][j]);语句外面加一个判断如果g[t][j]!=Integer.MAX_VLAUE时才进行更新操作(也就是结点t到结点j有边的时候才进行更新操作)
谢谢您,我后来也发现这个问题了
请问
t = -1的时候为什么dist[t] 不会数组越界?
条件用的或,先做的t == -1判断 成立不会做后面的判断
为什么不行呢
g是一个二维数组 你要写g[] 才是一维的数组
可以看看这个API 需要放神马
for (int[] row : g) Arrays.fill(row, 0x3f3f);这样