堆优化的dijkstra
对于dijkstra为单源最短路的算法,其未优化版本为直接遍历每个点来寻找到源点最近的点,再以该点去更新与之相连的点,直到将每个点都利用更新其他点,这样便寻找到了从源点K出发的到每个点的最短路。
对其优化,考虑到每次寻找最小距离的那个点去更新其他点,于此与最小根堆的性质相符,我们可以使用堆来取出最小距离元素,由此加速算法。 呃呃,请原谅我时间复杂度不会算╮(╯﹏╰)╭。
详细解释请参见代码;
代码如下
program heap_dijkstra;
type heaptype=record {堆类型,其包含两个域,dist存储该点到源点的距离,point存储该点编号}
dist,point:longint;
end;
link=^rec; {指针类型,基类型为记录,包含三个域,v为权值,s为起点,e为终点}
rec=record
e,v:longint;
s:link;
end;
var heap:array[1..1000] of heaptype; {堆}
reflect:array[1..1000] of longint; {堆中位置映射}
visited:array[1..1000] of boolean; {访问标记}
tot,i,j,k,m,n,s,e,v:longint;
vertex:array[1..1000] of link; {点集}
temp:heaptype;
p:link;
procedure insert(s,e,v:longint); {创建邻接表}
var p:link;
begin
new(p);
p^.e:=e;
p^.v:=v;
p^.s:=vertex[s];
vertex[s]:=p;
end;
procedure up(head,j:longint); {堆向上调整}
var i:longint;
begin
while (j>>1)>=head do
begin
i:=j>>1;
if heap[i].dist>heap[j].dist
then
begin
temp:=heap[i];
heap[i]:=heap[j];
heap[j]:=temp;
reflect[heap[i].point]:=i;
reflect[heap[j].point]:=j;
j:=i;
end
else
break;
end;
end;
procedure down(i,rear:longint); {堆向下调整}
var j:longint;
begin
while (i<<1)<=rear do
begin
j:=i<<1;
if (j<rear) and (heap[j].dist>heap[j+1].dist) then inc(j);
if heap[i].dist>heap[j].dist
then
begin
temp:=heap[i];
heap[i]:=heap[j];
heap[j]:=temp;
reflect[heap[i].point]:=i;
reflect[heap[j].point]:=j;
i:=j;
end
else
break;
end;
end;
begin
assign(input,'D:/input/heap_dijkstra.txt');{呃呃,文件可以直接略过}
reset(input);
assign(output,'D:/output/heap_dijkstra.txt');
rewrite(output);
readln(n,m,k);
for i:=1 to n do vertex[i]:=nil;
for i:=1 to m do
begin
readln(s,e,v);
insert(s,e,v);
end;
fillchar(visited,sizeof(visited),false);
for i:=1 to k-1 do {初始化堆,因为源点k无需入堆,所以第k个位置断开,k之前存的不变而k及k之后的位置存储后一个点,K让出了一个空}
begin
heap[i].dist:=maxlongint; {堆位置为i的到源点距离}
heap[i].point:=i;{映射 堆位置为i的存储的点编号为多少}
reflect[i]:=i; {映射 编号为i的点在堆中的位置为多少}
end;
for i:=k+1 to n do
begin
heap[i-1].dist:=maxlongint;
heap[i-1].point:=i;
reflect[i]:=i-1;
end;
p:=vertex[k];
while p<>nil do {创建表,存储源点相连点的最短路径,肯定一步到达,且还会后续更新}
begin
if p^.v<heap[reflect[p^.e]].dist
then
begin
heap[reflect[p^.e]].dist:=p^.v;
up(1,reflect[p^.e]);
end;
p:=p^.s;
end;
visited[k]:=true;
tot:=n-1;
heap[n].dist:=0;
heap[n].point:=k;
reflect[k]:=n;
while true do {Dijkstra 主程序 }
begin
if (heap[1].dist=maxlongint)
or (visited[heap[1].point])
then break;
{当堆首元素距离为maxlongint,或堆首都以访问肯定堆已经空}
p:=vertex[heap[1].point];
while p<>nil do
begin
if heap[1].dist+p^.v<heap[reflect[p^.e]].dist
then
begin
heap[reflect[p^.e]].dist:=heap[1].dist+p^.v;
up(1,reflect[p^.e]);
end;
p:=p^.s;
end;
{接下来出堆操作}
visited[heap[1].point]:=true;
temp:=heap[1];
heap[1]:=heap[tot];
heap[tot]:=temp;
reflect[heap[1].point]:=1;
reflect[heap[tot].point]:=tot;
dec(tot);
down(1,tot);
end;
for i:=1 to n do
begin
write(heap[reflect[i]].dist,' ');
end;
close(input);
close(output);
end.
希望有用。 有错误请指出,O(∩_∩)O谢谢。;
每日一句
从蛹破茧而出的瞬间,是撕掉一层皮的痛苦彻心彻肺 很多蝴蝶都是在破茧而出的那一刻 被痛得死掉了。
这句话就如马云说的一样。。。
未来就在眼前,放弃只会失去一切希望。