---恢复内容开始---
Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题。对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射。对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路。若存在负权回路,单源点最短路径问题无解;若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v]
Bellman—Ford算法流程
分为三个阶段:
(1)初始化:将除源点外的所有顶点的最短距离估计值
dis[v]ß+∞,dis[s]ß0;
(2)迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集v中的每个顶点v的最短距离估计值逐步逼近其最短距离;
(3)检验负权回路:判断边集E中的每一条边的两个端点是否收敛。如果存在未收敛的顶点,则算法返回false,表明问题无解;否则算法返回true,并且从源点可达的顶点v的最短距离保存在dis[v]中。
【程序】
1 {单源最短路径的Bellman-ford算法执行v-1次,每次对每条边进行松弛操作如有负权回路则输出"Error"} 2 const 3 maxn=100; 4 maxe=maxn*(maxn-1)div 2; 5 type 6 edge=record 7 a,b,w :integer; 8 end; 9 var 10 edges :array[1..maxe]of edge; 11 dis :array[1..maxn]of integer; 12 pre :array[1..maxn]of integer; 13 e,n,s :integer; 14 procedure init; 15 var 16 i :integer; 17 begin 18 e:=0; 19 assign(input,'g.in');reset(input); 20 readln(n,s); 21 while not eof do 22 begin 23 inc(e); 24 with edges[e] do readln(a,b,w); 25 end; 26 fillchar(dis,sizeof(dis),$7f);//初始值为无穷大 27 dis[s]:=0;pre[s]:=s; 28 end; 29 procedure relax(u,v,w:integer); 30 begin 31 if dis[u]+w<dis[v] then 32 begin 33 dis[v]:=dis[u]+w; 34 pre[v]:=u; 35 end 36 end; 37 function bellman_ford:boolean; 38 var 39 i,j :integer; 40 begin 41 for i:=1 to n-1 do 42 for j:=1 to e do 43 with edges[j] do relax(a,b,w); 44 for i:=1 to e do 45 with edges[i] do 46 if dis[a]+w<dis[b] then exit(false); 47 exit(true) 48 end; 49 procedure print_path(i:integer); 50 begin 51 if pre[i]<>s then print_path(pre[i]); 52 write('-->',i) 53 end; 54 procedure show; 55 var 56 i :integer; 57 begin 58 for i:=1 to n do 59 begin 60 write(i:3,':',dis[i]:3,':',s); 61 print_path(i); 62 writeln 63 end; 64 end; 65 {========main========} 66 begin 67 init; 68 if bellman_ford then show 69 else writeln('Error!!') 70 end.
---恢复内容结束---