算法:DIJ+HEAP
步骤:建一个小根堆,把权值都放进去,每次都在堆里面取出堆首,然后不断的维护这个堆,时间复杂度是O(nlogn),比之前O(n²)的算法快了不少。对于大数据时采用边表或前向星类似的数据结构存,能优化不少。
program NDK1068;
const
maxn=10000;
maxm=1000000;
type
atp=record
y,next,dis:longint;
end;
agp=record
x,data:longint;
end;
var
map:array [0..maxm] of atp;{map记录边的信息。}
v:array [0..maxn] of agp;{v[i].x表示在i位置上的数的原来的位置,v[i].data表示到堆中这个点的最小权值。}
first:array [0..maxn] of longint;{first记录边的信息。}
linkv:array [0..maxn] of longint;{linkv[i]表示原位置上的数现在在堆里的位置。实际上与v[i].x形成了相互的映射。}
n,m,tot,st,ed:longint;
procedure init;
var
i,x,y,dis:longint;
temp:agp;
begin
fillchar(first,sizeof(first),0);
fillchar(map,sizeof(map),0);
readln(n,m);
for i:=1 to m do
begin
readln(x,y,dis);
inc(tot);
map[tot].y:=y;
map[tot].dis:=dis;
map[tot].next:=first[x];
first[x]:=tot;
end;
for i:=1 to n do linkv[i]:=i;{初始化。}
for i:=1 to n do
begin
v[i].x:=i;
v[i].data:=maxlongint;
end;
readln(st,ed);
{这里首先要把起点和堆首交换一下,因为先设起点为最小的点。}
temp:=v[st];
v[st]:=v[1];
v[1]:=temp;
v[1].data:=0;
end;
procedure ad_up(x:longint);
var
temp:agp;
begin
while x shr 1>=1 do
begin
if v[x].data<v[x shr 1].data then
begin
temp:=v[x];
v[x]:=v[x shr 1];
v[x shr 1]:=temp;
{改变原位置上的数的现在的位置。}
linkv[v[x].x]:=x;
linkv[v[x shr 1].x]:=x shr 1;
x:=x shr 1;
end
else break;
end;
end;
procedure ad_down(i,m:longint);
var
temp:agp;
begin
while i shl 1<=m do
begin
i:=i shl 1;
if (v[i+1].data<v[i].data) and (i<m) then inc(i);
if v[i].data<v[i shr 1].data then
begin
temp:=v[i];
v[i]:=v[i shr 1];
v[i shr 1]:=temp;
{同上。}
linkv[v[i].x]:=i;
linkv[v[i shr 1].x]:=i shr 1;
end
else break;
end;
end;
procedure dij;
var
i,min,minp,t:longint;
temp:agp;
begin
for i:=1 to n do
begin
{取最小点,最小权值,同时把堆首跟堆尾元素进行交换。}
minp:=v[1].x;
min:=v[1].data;
linkv[v[1].x]:=n-i+1;
linkv[v[n-i+1].x]:=1;
temp:=v[1];
v[1]:=v[n-i+1];
v[n-i+1]:=temp;
{维护堆。}
ad_down(1,n-i);
t:=first[minp];
if min<>maxlongint then{判断能否到达堆首。}
begin
while t<>0 do
begin
if (map[t].dis+min<v[linkv[map[t].y]].data) and (linkv[map[t].y]<=n-i) then{后面的判断保证了要扩展的点在堆里。即尚未扩展。}
begin
v[linkv[map[t].y]].data:=map[t].dis+min;
ad_up(linkv[map[t].y]);{上调维护。}
end;
t:=map[t].next;
end;
end
else break;
end;
end;
begin
assign(input,'NDK1068.in'); reset(input);
assign(output,'NDK1068.out'); rewrite(output);
init;
dij;
if v[linkv[ed]].data<>maxlongint then writeln(v[linkv[ed]].data) else writeln('No Solution!');{输出。}
close(input); close(output);
end.