最短路径问题可用4种方法解决:
1.动态规划法(标号法)
2.Dijkstra算法
3.SPFA算法
4.Floyd算法
前三种算法的时间复杂度一般是O(n²)而Floyd算法的时间复杂度为O(n³)。
不过,Floyd算法适用于APSP(All Pairs Shortest Paths),是一种动态规划算法,稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。 优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单。
缺点:时间复杂度比较高,不适合计算大量数据。
例题: From Admin
A层次第二讲:小呆打车(taxi)
背景 Background
A层次第二讲第二题
描述 Description
寒假里,小呆要去位于A市的皮球家拜年。小呆来到A市的车站,买了一张A市的地图,他发现这里的地形非常的复杂。A市的街道一共有N个路口,M条道路,每条道路连接着两个路口,并且有各自的长度。目前,小呆所在的车站位于编号为1的路口,而皮球家所在的路口编号为N,小呆准备打出租车去,当然,路程越小,付的钱就越少。问题摆在眼前:请帮助小呆寻找一条最短路径,使得他可以花最少的钱到达皮球家。
输入格式 Input Format
输入文件的第一行有两个整数N;M,(N<=1000<=M)分别代表路口数和街道数。以下有M行用以描述各个街道,每行有三个数字P1;P2;L,分别代表此街道起点编号,此街道终点编号以及此街道的长度。保证所给的数据可以构成连通图。
输出格式 Output Format
输出文件中只要求出现一行,一个整数,说明最短路径的长度(<=maxlongint)。
program P1012_dijkstra;
const max=1000;
var g:array[1..1000,1..1000]of integer;
s:array[1..max]of boolean;
dist:array[1..max]of longint;
path:array[1..max]of integer;
i,j,k,n,min,vj:longint;
procedure print(i:integer);
var pre:integer;
begin
if i= 1 then write(1)
else begin print(path[i]);write('->',i);end;
end;
procedure init;
var i,j,a,b,s:integer;
begin
readln(n,s);
for i:=1 to n do
for j:=1 to n do
if (i<>j) then g[i,j]:=maxint;
for i:=1 to s do
readln(a,b,g[a,b]);
end;
begin
init;
fillchar(s,sizeof(s),false);
fillchar(path,sizeof(path),1);
for i:=1 to n do dist[i]:=g[1,i];
s[1]:=true;
for k:=1 to n-2 do
begin
min:=maxint;
for j:=1 to n do
if (dist[j]<min)and not s[j] then
begin
min:=dist[j];
vj:=j;
end;
s[vj]:=true;
for j:=1 to n do
if min+g[vj,j]<dist[j] then
begin
dist[j]:=min+g[vj,j];
path[j]:=vj;
end;
end;
//print(n);
writeln(dist[n]);
end.
const maxn=10000;
maxm=100000;
var
head,dis:array[0..maxn]of longint;
u:array[0..maxn]of boolean;
next,v,c:array[0..maxm]of longint;
d:array[0..1000000]of longint;
top,i,n,m,x,y,z,k:longint;
procedure add(x,y,z:longint);
begin
inc(top);v[top]:=y;c[top]:=z;next[top]:=head[x];head[x]:=top;
end;
procedure spfa;
var l,r:longint;
begin
fillchar(dis,sizeof(dis),$3f);
dis[1]:=0;l:=0;r:=1;d[1]:=1;
repeat
inc(l);
k:=head[d[l]];
while k<>0 do
begin
if dis[v[k]]>dis[d[l]]+c[k] then
begin
dis[v[k]]:=dis[d[l]]+c[k];
if not u[v[k]] then
begin
inc(r);
d[r]:=v[k];
u[v[k]]:=true;
end;
end;
k:=next[k];
end;
u[d[l]]:=false;
until l=r;
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y,z);
add(x,y,z);
end;
spfa;
writeln(dis[n]);
end.
Accepted code:
var d,sy:array [0..1001] of longint; s,a,b,w:array [0..1000001] of longint; v:array [0..1001] of boolean; n,m,now,l,r,i,y:longint; procedure sort(l,r:longint); var i,j,x:longint; begin i:=l;j:=r;x:=a[random(r-l+1)+l]; repeat while a[i]<x do inc(i); while x<a[j] do dec(j); if i<=j then begin y:=a[i];a[i]:=a[j];a[j]:=y; y:=b[i];b[i]:=b[j];b[j]:=y; y:=w[i];w[i]:=w[j];w[j]:=y; inc(i);dec(j); end; until i>j; if j>l then sort(l,j); if i<r then sort(i,r); end; begin readln(n,m); for i:=1 to m do begin readln(a[i],b[i],w[i]); a[i+m]:=b[i];b[i+m]:=a[i];w[i+m]:=w[i]; end; randomize; m:=m*2; sort(1,m); now:=0;i:=1; repeat while (i<=m) and (a[i]<=now) do inc(i); sy[now+1]:=i; inc(now); until now>=n; d[1]:=0; for i:=2 to n do d[i]:=maxlongint div 2; l:=1;r:=1;s[1]:=1; while l<=r do begin i:=sy[s[l]]; while a[i]=s[l] do begin if d[b[i]]>d[a[i]]+w[i] then begin d[b[i]]:=d[a[i]]+w[i]; if not v[b[i]] then begin inc(r); s[r]:=b[i]; v[b[i]]:=true; end; end; inc(i); end; v[s[l]]:=false; inc(l); end; writeln(d[n]); end.
转载于:https://www.cnblogs.com/shy-/archive/2012/05/16/2504638.html