迪杰斯特拉算法求最短路径(java)
设G=(V,E)是一带权的有向图,源点为v0,则迪杰斯特拉算法用来求v0到其他顶点的最短路径。迪杰斯特拉算法是按路径长度递增的次序产生最短路径的算法
以此图为例 求v0到v3最短路径的过程
dist[3]保存v0到v3的距离,最开始是无限大,即dist[3]=INF,所以迪杰斯特拉算法先找到v2,即dist[2] = 10
然后从v2出发,因为v2到v3距离为50(小于INF),即dist[2]+cost[2][3] < dist[3],然后更新dist[3] = 60
v0到其他点也是以上步骤,通过与v0相邻的点从而求出其他点的路径。
下面为代码
输入
6 8
0 2 10
0 4 30
0 5 100
1 2 5
2 3 50
3 5 10
4 3 50
4 5 60
输出
n为顶点个数,m为可达路径个数,二维数组cost是图的邻接矩阵表示。先把cost初始化为最大值,然后把可达路径依次填入当中。
这里稍微有点难理解的就是rear数组与q数组,其实稍微模拟一下步骤,就可以很容易理解。
刚开始初始化的时候,以v2,v3为例
q[2][0] = 0
q[2][1] = 2
rear[2] = 2
q[3][0] = 0
q[3][1] = 3
rear[3] = 2
这就相当于刚开始v0到v2的路径为0->2,v0到v3的路径为0->3
之后更新的时候,因为v0到v3需要经过v2,所以
q[3][0] = 0
q[3][1] = 2
q[3][2] = 3
rear[3] = 3
然后输出路径0->2->3
import java.util.Arrays;
import java.util.Scanner;
public class Dijkstra1 {
public static void main(String args[]){
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int[][] cost = new int[n][n];
for(int i = 0; i<n; i++){
Arrays.fill(cost[i], Integer.MAX_VALUE);
}
for(int i = 0; i<m; i++){
int x = scanner.nextInt();
int y = scanner.nextInt();
int p = scanner.nextInt();
cost[x][y] = p;
}
dijkstral(cost, 0, n);
}
public static void dijkstral(int[][] cost, int v, int n){
int[] dist = new int[n]; //保存v到其他点的最短距离
int[] s = new int[n]; //保存已计算过的顶点
int[] rear = new int[n]; //rear[i]保存v到顶点i的最短路径顶点数
int[][] q = new int[n][n]; //q[v][i]保存v到i的最短路径
//初始化s和rear
for(int i = 1; i<n; i++){
s[i] = 0;
rear[i] = -1;
}
//初始化dist和q
for(int i = 1; i<n; i++){
dist[i] = cost[v][i];
if(dist[i] < Integer.MAX_VALUE){
q[i][++rear[i]] = v;
q[i][++rear[i]] = i;
}
}
s[v] = 1;
int j, min, m;
for(int i = 0; i<n-1; i++){
min = Integer.MAX_VALUE;
m = v;
//寻找和v相邻的最短距离的点
for(j = 1; j<n; j++){
if(dist[j] < min && s[j] == 0){
min = dist[j];
m = j;
}
}
if(m != j){
s[m] = 1;
System.out.println(v + "到" + m + "的最短距离为" + dist[m]);
System.out.print("最短路径为: ");
for(int k = 0; k<=rear[m]; k++){
if(k == rear[m]) {
System.out.print(q[m][k]);
break;
}
System.out.print(q[m][k] + "->");
}
System.out.println();
//更新dist,就是上面所说的从v2出发
for(int k = 1; k<n; k++){
if(dist[k] > (cost[m][k] + dist[m]) && s[k] == 0 && cost[m][k] != Integer.MAX_VALUE){
dist[k] = cost[m][k] + dist[m];
for(int k1 = 0; k1<=rear[m]; k1++){ //更新路径
q[k][k1] = q[m][k1];
}
rear[k] = rear[m];
q[k][++rear[k]] = k;
}
}
}
}
}
}