最短路径四种解法

最短路径的四种解法

在学习“图”的时候,遇到过一道经典的题:最短路径。最短路径有四种最经典的解法。废话不多说,直接上代码。

弗洛伊德算法

//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( ̄▽ ̄)ブ

猜你喜欢

转载自blog.csdn.net/S_JH330206/article/details/107917887