1. 程式人生 > 實用技巧 >最短路徑四種解法

最短路徑四種解法

最短路徑四種解法

最短路徑的四種解法

在學習“圖”的時候,遇到過一道經典的題:最短路徑。最短路徑有四種最經典的解法。廢話不多說,直接上程式碼。

弗洛伊德演算法

//Floyd-Warshall
#include<iostream> 
using namespace std;
const int M=999999; 
int n,m,p1,p2,l;
int map[1000][1000];
int main()
{<!-- -->
 cin>>n>>m;
 for (int i=1;i<=n;i++)
 {<!-- -->
  for (int j=1;j<=n;j++)
  {<!-- -->
   if (i==j)
   {<!-- -->
    map[i][j]=0;
   }
   else
   {<!-- -->
    map[i][j]=M;
   }
  }
 }
 for (int i=1;i<=m;i++)
 {<!-- -->
  cin>>p1>>p2>>l;
  map[p1][p2]=l;
 }
  for (int k = 1; k <= n; k++) {<!-- -->
    for (int i = 1; i <= n; i++) {<!-- -->
      for (int j = 1; j <= n; j++) {<!-- -->
        if (map[i][j] > map[i][k] + map[k][j]) {<!-- -->
          map[i][j] = map[i][k] + map[k][j];
        }
      }
    }
}
 for (int i=1;i<=n;i++)
 {<!-- -->
  for (int j=1;j<=n;j++)
  {<!-- -->
   cout<<map[i][j];
  }
  cout<<endl;
 } 
 return 0;
}

弗洛伊德演算法的時間複雜度O(n³),多源、無負權邊,時效性較差。

迪傑斯特拉

//Dijkstra
#include <iostream>
using namespace std;
const int M=99999999;
int n,m,p1,p2,l,map[100][100],dis[1000],book[1000]={<!-- -->0},mi,u;
int main()
{<!-- -->
 cin>>n>>m;
 for (int i=1;i<=n;i++)
 {<!-- -->
  for (int j=1;j<=n;j++)
  {<!-- -->
   if (i==j)
   {<!-- -->
    map[i][j]=0;
   }
   else
   {<!-- -->
    map[i][j]=M;
   }
  } 
 }
 for (int i=1;i<=m;i++)
 {<!-- -->
  cin>>p1>>p2>>l;
  map[p1][p2]=l;
 }
 book[1]=1;
 for (int i=1;i<=n;i++)
 {<!-- -->
  dis[i]=map[1][i];
 } 
 for (int i=1;i<=n-1;i++)
 {<!-- -->
  mi=M;
  for (int j=1;j<=n;j++)
  {<!-- -->
   if (dis[j]<mi&&book[j]==0)
   {<!-- -->
    mi=dis[j];
    u=j;
   }
  }
  book[u]=1;
  for (int k=1;k<=n;k++)
  {<!-- -->
   if(map[u][k]<M)
   {<!-- -->
    if (dis[k]>dis[u]+map[u][k])
    {<!-- -->
     dis[k]=dis[u]+map[u][k];
    }
   }
  }
 }
 for (int i=1;i<=n;i++)
 {<!-- -->
  cout<<dis[i]<<" ";
 }
 return 0;
}

迪傑斯特拉的時間複雜度O(n²),單源、無負權,時效性較好。

貝爾曼·福特

//Bellman-Ford
#include <iostream>
using namespace std;
const int M=9999999;
int main()
{<!-- -->
 int n,m;
 cin>>n>>m;
 int p1[100],p2[100],l[100];
 int dis[1000];
 for (int i=1;i<=m;i++)
 {<!-- -->
  cin>>p1[i]>>p2[i]>>l[i];
 }
 for (int i=1;i<=n;i++)
 {<!-- -->
  dis[i]=M;
 }
 dis[1]=0;
 for (int i=1;i<=n-1;i++)
 {<!-- -->
  for (int j=1;j<=m;j++)
  {<!-- -->
   if (dis[p2[i]]>dis[p1[i]]+l[i])
   {<!-- -->
    dis[p2[i]]=dis[p1[i]]+l[i];
   }
  }
 }
 for (int i=1;i<=n;i++)
 {<!-- -->
  cout<<dis[i]<<" ";
 }
 return 0;
}

貝爾曼·福特的時間複雜度O(n²),單源、可以判斷是否為負權,時效性較好。

SPFA-貝爾曼·福特佇列優化

//SPFA
#include <iostream>
using namespace std;
const int inf=9999999;
int main()
{<!-- -->
 int n,m;
 cin>>n>>m;
 int p1[1000],p2[1000],l[1000];
 int dis[1000];
 int book[1000];
 int first[1000];
 int next[1000];
 int que[1000]={<!-- -->0};
 int tail=1,head=1;
 int k;
 for (int i=1;i<=n;i++) 
 {<!-- -->
  dis[i]=inf;
 }
 dis[1]=0;
 for (int i=1;i<=n;i++)
 {<!-- -->
  book[i]=0;
 }
 for (int i=1;i<=n;i++)
 {<!-- -->
  first[i]=-1;
 }
 int i;
 for (i=1;i<=m;i++)
 {<!-- -->
  cin>>p1[i]>>p2[i]>>l[i]; 
  next[i]=first[p1[i]];
  first[p1[i]]=i;
 }
 que[tail]=1;
 tail++;
 book[i]=1;
 while (head<tail)
 {<!-- -->
  k=first[que[head]];
  while(k!=1)
  {<!-- -->
   if (dis[p2[k]]>dis[p1[k]]+l[k])
   {<!-- -->
    dis[p2[k]]=dis[p1[k]]+l[k];
   }
   if (book[p2[k]]==0)
   {<!-- -->
    que[tail]=p2[k];
    tail++;
    book[p2[k]]=1;
   }
  }
  k=next[k];
  head++;
 }
 for (i=1;i<=n;i++)
 {<!-- -->
  cout<<dis[i]<<" ";
 } 
 return 0;
}

貝爾曼·福特佇列優化的時間複雜度最大為O(nm),最小為O(n),單源、可以判斷是否為負權,時效性相對好。 本文結束了,點個贊再走唄o( ̄▽ ̄)ブ</em>