图论-最短路Dijkstra算法 [JAVA实现版]
Dijkstra算法可以解决点与点最短路问题,也可以解决点与点可达问题,但是不适用于存在负权边的情况
测试数据
给定一个 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。 例子1: 3 3 1 2 2 2 3 1 1 3 4 输出> 3
代码实现
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static Scanner scanner = new Scanner(System.in);
static int max = 500;
static int maxL = 10000;
static int[] dp = new int[max+1];
static int[][] dis = new int[max+1][max+1];
static boolean[] confirm = new boolean[max+1];
public static void main(String[] args) {
// 最多有500个点,{a,b,dis}: a to b need dis
int s=1,e=scanner.nextInt();
init();
System.out.println("dst(s,e) = " + dst(s, e));
}
private static int dst(int s, int e) {
dp[s] = 0;
for (int i = 0; i < max; i++) {
int t = -1;
for (int j = 1; j <= max; j++) {
if(!confirm[j] && (t==-1 || dp[j]<dp[t]))
{
t = j;
}
}
confirm[t] = true;
for (int j = 1; j <= max; j++) {
dp[j] = Math.min(dp[j],dp[t] + dis[t][j]);
}
}
return dp[e]==maxL?-1:dp[e];
}
private static void init() {
Arrays.fill(dp,maxL);
for (int[] di : dis) {
Arrays.fill(di,maxL);
}
int m = scanner.nextInt();
for (int i = 0; i < m; i++) {
int a = scanner.nextInt();
int b = scanner.nextInt();
int d = scanner.nextInt();
dis[a][b] = Math.min(dis[a][b],d);
}
}
}
算法代码解释
1. 输入数据(实际上是边集),将数据构造成邻接矩阵,存在重边,取最小边 2. 初始化时,需要将dp、dis的元素都初始化为无穷,这是为了不影响判断,从意义来说,没确认的点的距离相互都是无穷 3. Dijkstra(N:点集的数量) - 将初始点s的距离置为0,因为初始点到初始点的距离可以确定 - 遍历N次,确认N个点的距离 - 每次遍历,都取出当前为确认的最小点t - 由最小点更新点集的所有点 bp[j] = Math.min(bp[j],bp[t]+dis[t,j]); - 最后确认comfirt[t] 4. 返回终点dp[e]