三种最短路径的算法(弗洛伊德(Floyd),SPFA,迪杰斯克拉(Dijkstra)) # 无讲解 #

弗洛伊德算法

Floyd算法,不允许所有权值为负的回路,可以求出任意两点间的最短距离

for(int k=1; k<=n; k++)
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            if(map[i][k]+map[k][j]<map[i][j])
                map[i][j]=map[i][k]+map[k][j];

在C++中可改写为

for(int k=1; k<=n; k++)
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            map[i][j]=min(map[i][k]+map[k][j],map[i][j])

讲解传送门
弗洛里德算法可解决多源最短路问题,but弗洛里德算法的复杂度为O(n^3) 容易TLE;

SPFA

为了避免最坏情况的出现,在正权图上应使用效率更高的Dijkstra算法。
若给定的图存在负权边,类似Dijkstra算法等算法便没有了用武之地,SPFA算法便派上用场了;
SPFA为Belleman–Ford的优化算法感兴趣的可以去看看bellman–ford算法


讲解传送门

Dijkstra(未优化)

这玩意和Prim算法可不是一般的像,还是不难理解的
PS:优化版是使用队列来消除一些冗余运算;同SPFA;

#include 
#include 
#define MAX 0x3f3f3f3f
using namespace std;
int Map[105][105],dis[105];
bool vis[105];
int n,m;
void Dijkstra( )
{
    int Min,pos;
    memset(vis,false,sizeof(vis));
    vis[1]=true;
    for(int i=1; i<=n; ++i)
    {
        dis[i]=Map[1][i];
    }
    for(int i=1; i<=n-1; ++i)
    {
        Min=MAX;
        for(int j=1; j<=n; ++j)
        {
            if(!vis[j]&&dis[j]<Min)
            {
                Min=dis[j];
                pos=j;
            }
        }
        vis[pos]=true;
        for(int j=1; j<=n; ++j)
        {
            if(!vis[j]&&Map[pos][j]+dis[pos]<dis[j])
            {
                dis[j]=Map[pos][j]+dis[pos];
            }
        }
    }
}

总结

  1. 计算多源路的最短路径:Floyd算法
  2. 计算单源正权路的最短路径:Dijkstra算法
  3. 计算含有负权路的最短路径(或判断是否含有负权路):SPFA算法

你可能感兴趣的:(算法)