poj3255,poj2449

这里介绍怎么求k短路

A*搜索 估价函数f[i]=g[i]+h[i];

在这里g[i]表示到达点i当前路径长,h[i]表示点i到达终点的最短距离

在搜索中,每次都取队列估价函数值最小的点,然后把它所能到达的点更新进入队列

显然这需要一个优先队列来维护(heap)

当终点第k次出队时,当前路径长度就是k短路

  1 const max=1000000000;
  2 type link=^node;
  3      node=record
  4        po,len:longint;
  5        next:link;
  6      end;
  7      point=record
  8        data,num:longint;
  9      end;
 10 var w,ow:array[0..1010] of link;
 11     v:array[0..1010] of boolean;
 12     d:array[0..1010] of longint;
 13     heap:array[0..1004010] of point;   //堆维护估价函数值
 14     st,en,i,n,m,j,t,k,x,y,z,s:longint;
 15     p:link;
 16 
 17 procedure sift(x:longint);    //堆的下沉
 18   var i,j:longint;
 19   begin
 20     i:=x;
 21     j:=i*2;
 22     while j<=t do
 23     begin
 24       if (j+1<=t) and (heap[j].data>heap[j+1].data) then inc(j);
 25       if heap[i].data>heap[j].data then
 26       begin
 27         swap(heap[i],heap[j]);
 28         i:=j;
 29         j:=i*2;
 30       end
 31       else exit;
 32     end;
 33   end;
 34 
 35 procedure up(x:longint);   //堆的上浮
 36   var i,j:longint;
 37   begin
 38     i:=x;
 39     j:=i div 2;
 40     while j>0 do
 41     begin
 42       if heap[i].data<heap[j].data then
 43       begin
 44         swap(heap[i],heap[j]);
 45         i:=j;
 46         j:=i div 2;
 47       end
 48       else exit;
 49     end;
 50   end;
 51 
 52 procedure add(x,y:longint;var q:link);
 53   var p:link;
 54   begin
 55     new(p);
 56     p^.po:=y;
 57     p^.len:=z;
 58     p^.next:=q;
 59     q:=p;
 60   end;
 61 
 62 procedure dij;     //求点到终点的距离
 63   var p:link;
 64   begin
 65     fillchar(v,sizeof(v),false);
 66     v[en]:=true;
 67     for i:=1 to n do
 68       d[i]:=max;
 69     d[en]:=0;
 70     p:=ow[en];
 71     while p<>nil do
 72     begin
 73       d[p^.po]:=min(d[p^.po],p^.len);   //用邻接表重要的细节
 74       p:=p^.next;
 75     end;
 76     for i:=1 to n-2 do
 77     begin
 78       x:=max;
 79       y:=0;
 80       for j:=1 to n do
 81         if not v[j] and (d[j]<x) then
 82         begin
 83           x:=d[j];
 84           y:=j;
 85         end;
 86       if x=max then exit;
 87       v[y]:=true;
 88       p:=ow[y];
 89       while p<>nil do
 90       begin
 91         d[p^.po]:=min(d[p^.po],p^.len+x);
 92         p:=p^.next;
 93       end;
 94     end;
 95   end;
 96 
 97 function astar(st,ed:longint):longint;
 98   var p:link;
 99   begin
100     heap[1].data:=d[st];
101     heap[1].num:=st;
102     t:=1;
103     s:=0;
104     astar:=-1;
105     while t<>0 do
106     begin
107       x:=heap[1].num;    //退队
108       y:=heap[1].data-d[x];  
109       swap(heap[1],heap[t]);
110       dec(t);
111       sift(1);
112       if x=en then
113       begin
114         s:=s+1;
115         if s=k then exit(y);
116       end;
117       p:=w[x];
118       while p<>nil do      //更新所有能到达的点入队
119       begin
120         inc(t);
121         heap[t].num:=p^.po;
122         heap[t].data:=y+p^.len+d[p^.po];
123         up(t);
124         p:=p^.next;
125       end;
126     end;
127   end;
128 
129 begin
130   readln(n,m);
131   for i:=1 to m do
132   begin
133     readln(x,y,z);
134     add(x,y,w[x]);
135     add(y,x,ow[y]);    //注意有向需反向建边,快速求点到终点的距离
136   end;
137   readln(st,en,k);
138   if st=en then inc(k);  //注意终点与起点重合时,路径为0的不算
139   dij;
140    writeln(astar(st,en));
141 end.
View Code

而对于poj3255,求无向图的次短路也可以用A*,在n<=5000时还是可以过的,注意那时候就不需要反向建边了

k短路算法还是很好理解的

原文地址:https://www.cnblogs.com/phile/p/4473282.html