1. 程式人生 > 其它 >No. 6.1 最短路徑之佛洛依德演算法

No. 6.1 最短路徑之佛洛依德演算法

一、Floyd-Warshall 演算法簡介:簡單優雅!

  如果要讓任意兩點之間的路程變短,只能引入另外的點集(請不要帶入兩點之間線段最短的真理,這裡不是直線!)

於是,可以將圖的二維平面,任意兩點之間的距離,通過引入其他的點,縮短路程,直到所有的點集相互之間路程都達到最短! 

  for(k=1;k<=n;k++)    //引入點集,判斷引入幾個可以達到最短路程
    for(i=1;i<=n;i++)   //判斷 i,j 兩點之間的距離
      for(j=1;j<=n;j++)
      {
        if(e[i][j] > e[i][k]+e[k][j])  //如果引入點集之後,路程變短,則視其為最短路程
        e[i][j]=e[i][k]+e[k][j];
      }

二、完整程式碼很簡單

int main(){
  int i,j,k,n,m;
  int a,b,c;
  int e[100][100];
  scanf("%d %d",&n,&m);

  for(i=1;i<=n;i++)  // initialize
    for(j=1;j<=n;j++)
    {
      if(i==j) e[i][j]=0;
      else e[i][j]=999999;
    }

  for(i=1;i<=m;i++)  // input manually
  {
    scanf("%d %d %d",&a,&b,&c);
    e[a][b]=c;
  }

  
  for(k=1;k<=n;k++)  // Floyd Warshall
    for(i=1;i<=n;i++)
      for(j=1;j<=n;j++)
      {
        if(e[i][j] > e[i][k]+e[k][j])
        e[i][j]=e[i][k]+e[k][j];
      }

  for(i=1;i<=n;i++)  // 這裡的 {} 不可以省略
  {

    for(j=1;j<=n;j++)
    {
      printf("%d\t",e[i][j]);
    }
    printf("\n");
  }
  getchar();getchar();return 0;
}

三、缺點:

1.演算法複雜度:相比深度搜索的O(N*N),廣度搜索更少,Floyd演算法複雜度是O(N*N*N)

2.隨著點集的擴大,要注意infinity的表示方式,比如有100條邊,每條邊不超過100的話,正無窮適當可設定為10000;

 當然直接用 inf 也無不可,if (e[i][k] < inf && e[k][j]< inf && e[i][j] > e[i][k] + e[k][j])

3.Floyd演算法不能解決帶有“負權環”的圖,這種圖沒有最短路徑。像這樣