单源最短路径的求法

来源:互联网 发布:吊带袜天使结局 知乎 编辑:程序博客网 时间:2024/04/30 08:09
2.最短路径
算法思想:
设图中有n个结点,设置一个集会u,存放已经求出最短路径的结点(初始时u中的元素是源点),v-u是尚未确定最短路径的顶点的集合。每次从v-u集合中找这样一个结点 best_jbest_ju集合中结点的邻接点,到源点的距离最短(等于到父结点的距离加上父结点到源点的距离)。然后把该best_j置入u集合中,直到u=v
 A.标号法求解单源点最短路径:
   var
     a:array[1..maxn,1..maxn] of integer;
     b:array[1..maxn] of integer; {b[i]
指顶点i到源点的最短路径}
     mark:array[1..maxn] of boolean;
   procedure bhf;
     var
       best,best_j:integer;
     begin
       fillchar(mark,sizeof(mark),false);
    mark[1]:=true; b[1]:=0;{1
为源点
}
    repeat
      best:=0;
        for i:=1 to n do{
双重循环,找到这样一个结点:所有已经标号的结点(包括源点)的邻接点中,到源点距离最短的点,j点到源点的距离是她到父节点的距离加上父节点到源点的距离,这里与prim算法求最小生成树的思想有点不同,prim是所有已经标号的结点的邻接点中,到父节点距离最短的点,
}
         If mark[i] then {
对每一个已计算出最短路径的点
}
          for j:=1 to n do
            if (not mark[j]) and (a[i,j]>0) then{j
未标号,是i的邻接点

           if (best=0) or (b[i]+a[i,j]<BEST) THEN {
因为b[1]0,所以best的第一个值是b[I,j] }
BEGIN
             best:=b[i]+a[i,j];  best_j:=j;
          end;
       if best>0 then begin
         b[best_j]:=best
mark[best_j]:=true;
       end;
     until best=0;
     end;{bhf}
总结:每次找best_j都要双重循环,原因是没有把未标号结点当前到源点的最短距离保存起来,还有优化的空间。
 
C. Dijkstra 算法:
var
     a:array[1..maxn,1..maxn] of integer;
     b,pre:array[1..maxn] of integer; {pre[i]
指最短路径上I的前驱结点
}
     mark:array[1..maxn] of boolean;
procedure dijkstra(v0:integer);
 begin
   fillchar(mark,sizeof(mark),false);
   for i:=1 to n do begin
     d[i]:=a[v0,i];
     if d[i]<>0 then pre[i]:=v0 else pre[i]:=0;
   end;
   mark[v0]:=true;
   repeat   {
每循环一次加入一个离1集合最近的结点并调整其他结点的参数
}
     min:=maxint; u:=0; {u
记录离1集合最近的结点
}
     for i:=1 to n do
       if (not mark[i]) and (d[i]<MIN) THEN
BEGIN
         u:=i; min:=d[i];
     end;
     if u<>0 then begin
       mark[u]:=true; 
       for i:=1 to n do
        if (not mark[i]) and (a[u,i]+d[u]<D[I]) THEN{
如果未标号的结点经过新标号的结点到源点的距离最短,则调整,这样d集合总是未标号结点到源点的最短距离}
BEGIN
          d[i]:=a[u,i]+d[u];
          pre[i]:=u;
       end;
     end;
   until u=0;
 end;
 
 
原创粉丝点击