最短路径

单源最短路径

dijkstra算法:
procedure dijkstra(s:longint);
var
  i,k,pos,min:longint;
begin
  fillchar(used,sizeof(used),false);
  for i:=1 to n do
    d[i]:=w[s,i];
  used[s]:=true;
  d[s]:=0;
  for K:=1 to n-1 do
    begin
     min:=maxlongint;
      fori:=1 to n do
       if (not used[i]) and (d[i]
         begin
          min:=d[i];
          pos:=i;
         end;
     used[pos]:=true;{pos即为该点的前一个点,以此可以保存最短路径}
      fori:=1 to n do
       if (not used[i]) and(d[i]>d[pos]+w[pos,i]) then
         d[i]:=d[pos]+w[pos,i];
    end;
end;


BELLMANFORD算法:{可判断负权回路}{还可改装成无正权回路的最长路径}
procedure init;
var
 i:longint;
begin
  fillchar(dist,sizeof(dist),127);
  dist[s]:=0;
  readln(nv,ne);
  for i:=1 to ne do
    readln(e[i].u,e[i].v,e[i].w);
end;
function relaxed(u,v,w:longint):boolean;
begin
  if dist[u]+w<dist[v] then
   begin
     dist[v]:=dist[u]+w;
     relaxed:=true;
   end
  else relaxed:=false;
end;
function bellmanford:boolean;{返回true时,dist[i]中存的便是s>i的最短路}
var
  i,j:longint;
begin
  flag:=false;
  for i:=1to nv-1 do
    begin
      for j:=1 to nedo
        if relaxed(e[j].u,e[j].v,e[j].w) then flag:=true;
     if flag=false then break;{这个优化很重要,可以从1600ms变为300ms,而且很方便}
     flag:=false;
   end;
  for i:=1 to k do
   if dist[e[i].u]+e[i].w<dist[e[i].v] then exit(false);
 exit(true);
end;

SPFA算法:{使用队列,但一个点可以多次入队}{O(ke),k约等于2}
var
  n,e,i:longint;
  q:array[1..10000] of longint;{队列}
  d:array[1..10000] of longint;{存最短路径}
  w:array[1..100,1..100] of longint;{存图}
  f:array[1..100] of boolean;{是否在队列内}
  t:array[1..100] of longint;{记录入队列的次数}
procedure init;
var
  i,a,b:longint;
begin
  read(n,e);
  fillchar(d,sizeof(d),127);
  fillchar(w,sizeof(w),0);
  fillchar(f,sizeof(f),false);
  fillchar(q,sizeof(q),0);
  fillchar(t,sizeof(t),0);
  for i:=1 to e do
    read(a,b,w[a,b]);
end;
function relaxed(u,v:longint):boolean;
begin
  if (w[u,v]<>0) and (d[u]+w[u,v]<d[v]) then{u即为最短路中v的前一个点}
    begin
      d[v]:=d[u]+w[u,v];
      exit(true);
    end;
  exit(false);
end;
function spfa(s:longint):boolean;
var
  head,tail,v:longint;
begin
  head:=0;
  tail:=0;
  inc(tail);
  q[tail]:=s;
  f[s]:=true;
  d[s]:=0;
  inc(t[s]);
  while head<>tail do
    begin
      head:=(head mod n)+1;
      v:=q[head];
      f[v]:=false;
      for i:=1 to n do
        if relaxed(v,i) then
          if not f[i] then{一个点更新其它点的最短路后,可能本身也被其他点更新}
            begin
              tail:=(tail mod n)+1;
              q[tail]:=i;
              f[i]:=true;
              inc(t[i]);
              if t[i]=n then exit(false);{如果一个点入队列超过n次,就说明途中存在负权回路}{注意啦,这只能判断源点所处的强连通分量内是不是有负权回路}
            end;
    end;
  exit(true);
end;
begin
  init;
  if spfa(1) then for i:=1 to n do write(d[i],' ')
  else writeln('error!');
end.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值