弗洛伊德算法
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 <iostream>
#include <memory.h>
#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];
}
}
}
}
总结
- 计算多源路的最短路径:Floyd算法
- 计算单源正权路的最短路径:Dijkstra算法
- 计算含有负权路的最短路径(或判断是否含有负权路):SPFA算法