古詩詞大全網 - 四字成語 - SPFA 原理 pascal語言

SPFA 原理 pascal語言

SPFA——Shortest Path Faster Algorithm,它可以在O(kE)的時間復雜度內求出源點到其他所有點的最短路徑,可以處理負邊。SPFA的實現甚至比Dijkstra或者Bellman_Ford還要簡單:

設Dist[I]代表S到I點的當前最短距離,Fa[I]代表S到I的當前最短路徑中I點之前的壹個點的編號。開始時Dist全部為+∞,只有Dist[S]=0,Fa全部為0。

維護壹個隊列,裏面存放所有需要進行叠代的點。初始時隊列中只有壹個點S。用壹個布爾數組記錄每個點是否處在隊列中。

每次叠代,取出隊頭的點v,依次枚舉從v出發的邊v->u,設邊的長度為len,判斷Dist[v]+len是否小於Dist[u],若小於則改進Dist[u],將Fa[u]記為v,並且由於S到u的最短距離變小了,有可能u可以改進其它的點,所以若u不在隊列中,就將它放入隊尾。這樣壹直叠代下去直到隊列變空,也就是S到所有的最短距離都確定下來,結束算法。

SPFA在形式上和寬度優先搜索非常類似,不同的是寬度優先搜索中壹個點出了隊列就不可能重新進入隊列,但是SPFA中壹個點可能在出隊列之後再次被放入隊列,也就是壹個點改進過其它的點之後,過了壹段時間可能本身被改進,於是再次用來改進其它的點,這樣反復叠代下去。設壹個點用來作為叠代點對其它點進行改進的平均次數為k,有辦法證明對於通常的情況,k在2左右(怎麽證明的作者也不知道)。

const maxl=maxlongint;

var

g:array[1..100,1..100]of shortint;

b:array[1..1000]of boolean;

h,dis:array[1..1000]of longint;

x,s,e,i,j:longint;

procedure inp;

begin

assign(input,'spfa.txt');reset(input);

readln(x,s,e);

for i:=1 to x do begin

for j:=1 to x do read(g[i,j]);

readln;

end;

for i:=1 to 1000 do dis[i]:=maxl;

fillchar(b,sizeof(b),false);

end;

procedure spfa;

var

head,tail:longint;

procedure relax(i:longint);

begin

if dis[i]>dis[h[head]]+g[h[head],i] then begin

if i=s then begin writeln('NO WAY');halt;end;

dis[i]:=dis[h[head]]+g[h[head],i];

if not b[i] then begin

inc(tail);

h[tail]:=i;

b[i]:=true;

end;

end;

end;

begin

head:=1;tail:=1;

h[1]:=s;

dis[s]:=0;

b[s]:=true;

repeat

for i:=1 to x do

if g[h[head],i]<>100 then relax(i);

b[h[head]]:=false;

inc(head);

until head>tail;

end;

begin

inp;

spfa;

writeln(dis[e]);

end.