JAVA之單源最短路徑(Single Source Shortest Path,SSSP問題)dijkstra算法求解


題目簡介:給定一個帶權有向圖,再給定圖中一個頂點(源點),求該點到其他所有點的最短距離,稱為單源最短路徑問題。

如下圖,求點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();
    }

}

 

運行結果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM