題目簡介:給定一個帶權有向圖,再給定圖中一個頂點(源點),求該點到其他所有點的最短距離,稱為單源最短路徑問題。
如下圖,求點1到其他各點的最短距離
准備工作:以下為該題所需要用到的數據
int N; //保存頂點個數
int M; //保存邊個數
int max; //用來設定一個比所有邊的權都大的值,來表示兩點間沒有連線
int[] visit; //找到一個頂點的最短距離,就把它設為1,默認為0(即還沒有找到)
int[][] distance; //保存圖中個邊的值,兩點間無邊則設為max
int[] bestmin; //保存源點到其他各點的最短距離,用於最后輸出
String[] path; //有些題目會要求輸出路徑,保存輸出路徑
算法步驟:
①找出與源點距離最短的那個點,即遍歷distance[1][1],distance[1][2],.....distance[1][N]中的最小值,如題:
源點1到2,4,5的距離分別為10,30,100,。3無法直接到達即此時distance[1][3] = max。那么這一步找出的點就是
頂點2。此時distance[1][2]即為源點1到頂點2的最短距離。將visit[2]設為1(頂點2完成)。
②松弛操作,
以①找出的點作為中心點(此時為頂點2),去遍歷visit[i]為0的點,如果distance[1][2] + distance[2][i] < distance[1][i]
就把新的較短路徑賦值給它,即distance[1][i] = distance[1][2] + distance[2][i],
此時頂點2能到達的點只有頂點3,並且distance[1][3] = max ,所以更新distance[1][3]的值為distance[1][2] + distance[2][3] = 60
完成以上兩個步驟后回到步驟①,即這是個循環,每次循環能找出一個最短距離的點和更新其他點,所以該循環要遍歷
N-1次就可以把所有點最短距離找出,大概過程如下:
for(int i = 2; i <= N; i++) {
步驟①(在一個循環內找到距離最短的點)
步驟②(以①找到的點為中心,通過一個循環更新所有visit[i]為0的點到源點的距離)
}
完整代碼如下:
package algorithm; import java.util.Scanner; public class Dijkstra__Single_Source_Shortest_Path { private static int N; private static int M; private static int max; private static int[] visit; private static int[][] distance; private static int[] bestmin; private static String[] path; public static void Dijkstra() { visit[1] = 1; bestmin[1] = 0; //大循環(搞定這里就算搞定該算法了,后面的輸出什么的可以不看) for(int l = 2; l <= N; l++) { int Dtemp = max; int k = -1; //步驟① for(int i = 2; i <= N; i++) { if(visit[i] == 0 && distance[1][i] < Dtemp) { Dtemp = distance[1][i]; k = i; } } visit[k] = 1; bestmin[k] = Dtemp; //步驟② for(int i = 2; i <= N; i++) { if(visit[i] == 0 && (distance[1][k] + distance[k][i]) < distance[1][i]) { distance[1][i] = distance[1][k] + distance[k][i]; path[i] = path[k] + "-->" + i; } } } //輸出路徑 for(int i=1;i<=N;i++) { System.out.println("從"+1+"出發到"+i+"的最短路徑為:"+path[i]); } System.out.println("====================================="); for(int i = 1; i <= N; i++) { System.out.println("從1出發到" + i + "點的最短距離為:" + bestmin[i]); } } public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); System.out.print("請輸入節點個數N,路徑總數M: "); N = input.nextInt(); M = input.nextInt(); max = 10000; bestmin = new int[N+1]; distance = new int [N+1][N+1]; visit = new int[N+1]; path=new String[N+1]; for(int i = 1; i <= N; i++) { for(int j = 1; j <= N; j++) { if(i == j) { distance[i][j] = 0; }else { distance[i][j] = max; } } bestmin[i] = max; path[i] = new String("1-->" + i); } System.out.println("請輸入" + M +"條數據x,y,z(表示x點到y點的距離為z):"); for(int i = 1; i <= M; i++) { int x = input.nextInt(); int y = input.nextInt(); int z = input.nextInt(); distance[x][y] = z; } input.close(); Dijkstra(); } }
運行結果如下: