题目
给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值。
请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。
输入格式
第一行包含整数n和m。
接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。
输出格式
输出一个整数,表示1号点到n号点的最短距离。
如果路径不存在,则输出-1。
数据范围
1≤n≤500,
1≤m≤105,
图中涉及边长均不超过10000。
输入样例:
3 3
1 2 2
2 3 1
1 3 4
输出样例:
3
思路分析
朴素迪杰斯特拉算法适用于求没有负边的最短路径,具体流程很简单,只有三步(+初始化)
- 初始化: 初始化图的边的信息为无穷,同时初始化源节点的距离为0
- 正式算法:(进行n次迭代,一次解决一个节点)
- 找到集合外距离源点最短距离的节点
- 将此节点加入集合中
- 更新所有的节点距离(因为集合内的节点就是最终结果了,所以可以直接跳过集合内的结点,只更新集合外的节点距离)
定义变量
此算法必须要定义的变量:
st[]
用于存储确定集合INF
用于存储不相连的边的权值
邻接矩阵需要定义的变量:
-
g[][]
:用于存储两节点间边的信息 -
dis[]
:用于存储节点到源的距离信息初始化时定义源节点距离为0
dis[1]=0
,其余均为INF
源代码
import java.util.*;
class Main{
static int N=510;
static int[][] g=new int[N][N];
static int[] dis=new int[N];
static boolean[] st=new boolean[N];
static int n;
static int m;
static int INF=0x3f3f3f;
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++){
for(int j=1;j<=n;j++){
g[i][j]=INF;
}
}
Arrays.fill(dis,INF);
while(m-->0){
int x=sc.nextInt();
int y=sc.nextInt();
int z=sc.nextInt();
g[x][y]=Math.min(g[x][y],z);
}
System.out.print(djs());
}
public static int djs(){
dis[1]=0;
for(int i=0;i<n;i++){
int t=-1;
for(int j=1;j<=n;j++){
if((t==-1||dis[j]<dis[t])&&(!st[j])){
t=j;
}
}
st[t]=true;
for(int j=1;j<=n;j++){
if(!st[j]){
dis[j]=Math.min(dis[j],dis[t]+g[t][j]);
}
}
}
if(dis[n]==INF) return -1;
return dis[n];
}
}