浅(瞎)谈(吹)最短路径算法总结(Floyd,Bellmen-ford,Dijkstra,Spfa)——————《最短路·终章》
V:点数
E : 边数
Dijkstra
:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度
O(E+V log V)
Bellman-Ford
:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE)
基本标程 AC Pascal代码:
var
n,m,x,y,i,j,bj:longint;
a,b,c,dis:array[-10005..1000005] of longint;
begin
readln(n,m,x,y);
for i:=1 to m do
readln(a[i],b[i],c[i]);
for i:=1 to n do
dis[i]:=maxlongint div 2;
dis[x]:=0;
for i:=1 to n-1 do
begin
bj:=0;
for j:=1 to m do
begin
if dis[b[j]]>dis[a[j]]+c[j] then
begin
dis[b[j]]:=dis[a[j]]+c[j];
bj:=1;
end;
if dis[a[j]]>dis[b[j]]+c[j] then
begin
dis[a[j]]:=dis[b[j]]+c[j];
bj:=1;
end;
end;
if bj=0 then
break;
end;
writeln(dis[y]);
end.
附上AC C++代码:
#include <cstdio>
#include <iostream>
using namespace std;
bool bj;
int n,m,x,y,i,j,a[1000005],b[1000005],c[1000005],dis[1000005];
int main()
{
scanf("%d%d%d%d",&n,&m,&x,&y);
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i],&b[i],&c[i]);
}
for (i=1;i<=n;i++)
{
dis[i]=100000005;
}
dis[x]=0;
for (i=1;i<=(n-1);i++)
{
bj=false;
for (j=1;j<=m;j++)
{
if (dis[b[j]]>dis[a[j]]+c[j])
{
dis[b[j]]=dis[a[j]]+c[j];
bj=true;
}
if (dis[a[j]]>dis[b[j]]+c[j])
{
dis[a[j]]=dis[b[j]]+c[j];
bj=true;
}
}
if (bj==false)
{
break;
}
}
printf("%d",dis[y]);
return 0;
}
SPFA(Bellman-Ford优化)
:适用于权值有负值,且没有负圈的图的单源最短路径,论文中的复杂度O(kE),k为每个节点进入Queue的次数,且k一般<=2,但此处的复杂度证明是有问题的,其实SPFA的最坏情况应该是O(VE).
Floyd
:每对节点之间的最短路径。多元最短路径,适用于权值为正负都可,O(n^3).
基本标程 AC Pascal代码:
var
n,m,i,j,k,a,b,ans,max:longint;
map:array[1..1005,1..1005]of int64;
begin
readln(n,m);
for i:=1 to n do
for j:=1 to n do
map[i,j]:=maxlongint;
for i:=1 to m do
begin
readln(a,b,ans);
map[a,b]:=ans;
map[b,a]:=ans;
end;
for k:=1 to n do
for i:=1 to n do
for j:=1 to n do
if map[i,k]+map[k,j]<map[i,j] then
map[i,j]:=map[i,k]+map[k,j];
max:=-maxlongint;
for i:=1 to n do
if (map[1,i]<>maxlongint) and (map[1,i]>max) then
max:=map[1,i];
writeln(max);
end.
附上AC C++代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#include<set>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 101
#define MOD 123
#define E 1e-6
using namespace std;
int g[N][N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
g[i][j]=0;
else
g[i][j]=INF;
}
}
for(int i=1;i<=m;i++)
{
int x,y,w;
cin>>x>>y>>w;
g[x][y]=w;
g[y][x]=w;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(g[i][j]>g[i][k]+g[k][j])
g[i][j]=g[i][k]+g[k][j];
int maxx=-INF;
for(int i=1;i<=n;i++)
if(g[1][i]>maxx)
maxx=g[1][i];
if(maxx==INF)
cout<<"-1"<<endl;
else
cout<<maxx<<endl;
return 0;
}