1. 程式人生 > >最短路之——弗洛伊德演算法(floyd)

最短路之——弗洛伊德演算法(floyd)

來源: https://blog.csdn.net/riba2534/article/details/54562440


我們要做的是求出從某一點到達任意一點的最短距離,我們先用鄰接矩陣來建圖,map[i][j]表示從i點到j點的距離,把自己到自己設為0,把自己到不了的邊初始化為無窮大,程式碼為:

  1. //初始化
  2.     for(int i=1; i<=n; i++)  
  3.         for(int j=1; j<=n; j++)  
  4.             if(i==j)  
  5.                 map[i][j]=0;  
  6.             else
  7.                 map[i][j]=inf;  
  8.     //讀入邊
  9.     for(int i=1; i<=m; i++)  
  10.     {  
  11.         scanf("%d%d%d",&t1,&t2,&t3);  
  12.         map[t1][t2]=t3;  
  13.     }  
最後,建好的圖可以用表格來表示:

現在,我們來思考,假設我們來找一箇中轉的點,看他們的路程會不會改變,我們先以1號頂點作為中轉點最為例子,製圖:


我們發現,圖有了變化,我們怎麼判斷以1號頂點作為中轉點圖的路程是不是更短呢,我們只需要判斷map[i][1]+map[1][j]的路程是不是比map[i][j]的路程更短,就可以判斷,

程式碼為:

  1. for(
    int i=1; i<=n; i++)  
  2.     for(int j=1; j<=n; j++)  
  3.         if(map[i][1]+map[1][j]<map[i][j])  
  4.             map[i][j]=map[i][1]+map[1][j];  
現在該怎麼辦呢,我們接著以2號頂點作為中轉點,很簡單程式碼修改一句就就可以:
  1. for(int i=1; i<=n; i++)  
  2.     for(int j=1; j<=n; j++)  
  3.         if(map[i][2]+map[2][j]<map[i][j])  
  4.             map[i][j]=map[i][2]+map[2][j];  
現在我們是不是發現了一個規律,只要不斷的遍歷每一個點,並且以每一個點作為中轉點看看它的值會不會改變,就可以得到從一個點到任意一個點的最短路徑,也就是多源最短路,這就是弗洛伊德演算法,程式碼為:
  1. for(int k=1; k<=n; k++)  
  2.     for(int i=1; i<=n; i++)  
  3.         for(int j=1; j<=n; j++)  
  4.             if(map[i][k]+map[k][j]<map[i][j])  
  5.                 map[i][j]=map[i][k]+map[k][j];  
這樣就可以遍歷每個頂點,找出所有的最短路,演算法的複雜度為O(n^3).

對於我一開始提出的問題,完整的程式碼為:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <string>
  4. #include <iostream>
  5. #include <stack>
  6. #include <queue>
  7. #include <vector>
  8. #include <algorithm>
  9. #define mem(a,b) memset(a,b,sizeof(a))
  10. usingnamespace std;  
  11. constint inf=1<<29;  
  12. int main()  
  13. {  
  14.     int map[10][10],n,m,t1,t2,t3;  
  15.     scanf("%d%d",&n,&m);//n表示頂點個數,m表示邊的條數
  16.     //初始化
  17.     for(int i=1; i<=n; i++)  
  18.         for(int j=1; j<=n; j++)  
  19.             if(i==j)  
  20.                 map[i][j]=0;  
  21.             else
  22.                 map[i][j]=inf;  
  23.     //讀入邊
  24.     for(int i=1; i<=m; i++)  
  25.     {  
  26.         scanf("%d%d%d",&t1,&t2,&t3);  
  27.         map[t1][t2]=t3;  
  28.     }  
  29.     //弗洛伊德(Floyd)核心語句
  30.     for(int k=1; k<=n; k++)  
  31.         for(int i=1; i<=n; i++)  
  32.             for(int j=1; j<=n; j++)  
  33.                 if(map[i][k]+map[k][j]<map[i][j])  
  34.                     map[i][j]=map[i][k]+map[k][j];  
  35.     for(int i=1; i<=n; i++)  
  36.     {  
  37.         for(int j=1; j<=n; j++)  
  38.             printf("%10d",map[i][j]);  
  39.         printf("\n");  
  40.     }  
  41.     return 0;  
  42. }