最短路径四种解法

最短路径四种解法

最短路径的四种解法

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

弗洛伊德算法

//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>

posted @ 2021-01-12 16:23  刘桓湚  阅读(916)  评论(0编辑  收藏  举报