分類: 其他
2010-11-21 22:29
191人閱讀收藏
舉報演算法
優化output
algorithm
input儲存
先說說spfa演算法:
spfa演算法
來自"nocow"
演算法簡介
spfa(shortest path faster algorithm)是
bellman-ford演算法
的一種佇列
實現,減少了不必要的冗餘計算。也有人說spfa本來就是bellman-ford演算法,現在廣為流傳的
bellman-ford演算法
實際上是山寨版。
演算法流程
演算法大致流程是用乙個佇列來進行維護。初始時將源加入佇列。每次從佇列中取出乙個元素,並對所有與他相鄰的點進行
鬆弛,若某個相鄰的點鬆弛成功,則將其入隊。直到隊列為空時演算法結束。
這個演算法,簡單的說就是佇列優化的bellman-ford,利用了每個點不會更新次數太多的特點發明的此演算法
spfa——shortest path faster algorithm,它可以在o(ke)的時間複雜度內求出源點到其他所有點的最短路徑,可以處理負邊。spfa的實現甚至比dijkstra或者bellman_ford還要簡單:
設dist代表s到i點的當前最短距離,fa代表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到所有的最短距離都確定下來,結束演算法。若乙個點入隊次數超過n,則有負權環。
接下來是前向星:
前向星優化:[cpp]view plain
copy
不要把前向星想成什麼高深莫測的東西……它其實就是一種鄰接表的緊縮儲存形式。
為什麼叫前向星?因為它是將邊按照前端點排序,並用乙個陣列k[i]記錄端點i第一次以左端點出現的位置。這樣,我們就能用o(e)的空間複雜度儲存下乙個鄰接表,而避免了鍊錶或n^2的龐大空間消耗。
當然,實際上我們並不需要排序:因為我們只需要知道某一條邊應該放到什麼位置即可。因而我們還需要乙個陣列t[i]儲存從i出發的邊的條數。則需要儲存在的位置就可以很輕易地求得。(詳見**,以usaco中的butter為例)
butter題目**如下:program butter(input,output);
type
edge=record
x,y,d:longint;
end;
var
min,res,n,p,c,x,y,i,j,l,r:longint;
te,e:array[0..3000] of edge;
tk,t,k,num,d:array[1..800] of longint;
q:array[1..100000] of longint;
use:array[1..800] of boolean;
procedure swap(var n1,n2:longint);
var
tmp:longint;
begin
tmp:=n1;n1:=n2;n2:=tmp;
end;
begin
assign(input,'butter.in'
);reset(input);
readln(n,p,c);
fori:=1 to n
dobegin
read(x);
inc(num[x]);
end;
fori:=1 to c
dobegin
with e[i*2-1] do
readln(x,y,d);
e[i*2]:=e[i*2-1];
swap(e[i*2].x,e[i*2].y);
end;
c:=c*2;
fori:=1 to c
doinc(t[e[i].x]);
j:=0;k[1]:=1;
fori:=2 to p
dok[i]:=k[i-1]+t[i-1];
tk:=k;te:=e;
fori:=1 to c
dobegin
e[tk[te[i].x]]:=te[i];
inc(tk[te[i].x]);
end;
min:=maxlongint;
fori:=1 to p
dobegin
fillchar(q,sizeof
(q),0);
fillchar(d,sizeof
(d),127);
fillchar(use,sizeof
(use),
false
);
q[1]:=i;l:=1;r:=1;d[i]:=0;use[i]:=true
; repeat
forj:=k[q[l]] to k[q[l]]+t[q[l]]-1
doif
d[q[l]]+e[j].d
begin
d[e[j].y]:=d[q[l]]+e[j].d;
ifnot use[e[j].y] then
begin
use[e[j].y]:=true
; inc(r);
q[r]:=e[j].y;
end;
end;
use[q[l]]:=false
; inc(l);
until l>r;
res:=0;
forj:=1 to p
dores:=res+d[j]*num[j];
ifres
end;
assign(output,'butter.out'
);rewrite(output);
writeln(min);close(output);
end.
最短路(SPFA 前向星
problem description 輸入t,n分別代表有t條通道,和n個地點。接下來t行u,v,w分別表示u地點於v地點之間通道消費,有重複邊 sample input 5 51 2 20 2 3 30 3 4 20 4 5 20 1 5 100 sample output 運用spfa的幾個要...
C 最短路 spfa 前向星
time limit 7000ms memory limit 65536k 有疑問?點這裡 給出乙個帶權無向圖,包含n個點,m條邊。求出s,e的最短路。保證最短路存在。多組輸入。對於每組資料。第一行輸入n,m 1 n n 5 10 5,1 m m 2 10 6 接下來m行,每行三個整數,u,v,w,...
暢通工程續(SPFA 鏈式前向星)
傳送門 hdu 1874 某省自從實行了很多年的暢通工程計畫後,終於修建了很多路。不過路多了也不好,每次要從乙個城鎮到另乙個城鎮時,都有許多種道路方案可以選擇,而某些方案要比另一些方案行走的距離要短很多。這讓行人很困擾。現在,已知起點和終點,請你計算出要從起點到終點,最短需要行走多少距離。本題目包含...