迪傑斯特拉算法求最短路徑(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;
}
}
}
}
}
}