题目:星门跳跃
问题编号:341
题目描述
在EVE游戏中,宇宙被划分成为许多区域,每个区域中都有数目不定的星门,可以通过星门来跳跃到特定的区域(星门是双向的)。
现在你正参与BBE联军与MLGBD联盟的会战,但由于飞船受损,需要尽快回到后方的友军空间站进行维护。
试编写程序,计算出所须的最短的返回空间站时间。
为了简化问题,我们约定飞船所在的位置为区域1,空间站所在的位置为区域N。
问题规模:
对于80%的数据,1<N<=10000,1<M<50000;
对于100%的数据,1<N<=30000,1<M<150000,1<=X[],Y[]<=N,1<=Z[]<=4096;
输入格式
第1行,两个整数N,M,分别为区域的总数和星门的总数;
第2..M+1行,每行三个整数X[i],Y[i],Z[i],分别为星门连接的两个区域,以及跳跃所需时间;
输出格式
一个整数,返回空间站所需的最短时间。
样例输入
样例一
5 3
1 4 5
4 5 1
1 2 7
样例二
10 11
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9
8 9 10
9 10 11
1 5 7
6 9 3
样例输出
样例一
6
样例二
28
=================
裸的SPFA
========================
type
pnode=^node;
node=record
x,t:longint;
next:pnode;
end;
var
n,m:longint;
ti:array[1..30000]of pnode;
dis:array[1..30000]of longint;
f_bo:array[1..30000]of boolean;
h:array[1..200000]of longint;
procedure init;
begin
assign(input,'rq341.in');
assign(output,'rq341.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure insert(x,y,t:longint);
var
p:pnode;
begin
new(p);
p^.t:=t; p^.x:=y;
p^.next:=ti[x]; ti[x]:=p;
end;
procedure spfa;
var
l,r:longint;
x:longint;
p:pnode;
begin
fillchar(dis,sizeof(dis),$7);
fillchar(f_bo,sizeof(f_bo),true);
dis[1]:=0;
f_bo[1]:=false;
l:=0; r:=1;
h[r]:=1;
repeat
inc(l);
x:=h[l];
p:=ti[x];
while p<>nil do
begin
if dis[x]+p^.t<dis[p^.x] then
begin
dis[p^.x]:=dis[x]+p^.t;
if f_bo[p^.x] then
begin
inc(r);
h[r]:=p^.x;
f_bo[p^.x]:=false;
end;
end;
f_bo[x]:=true;
p:=p^.next;
end;
until l>=r;
writeln(dis[n]);
end;
procedure main;
var
i:longint;
x,y,t:longint;
begin
readln(n,m);
for i:=1 to n do ti[i]:=nil;
for i:=1 to m do
begin
readln(x,y,t);
insert(x,y,t);
insert(y,x,t);
end;
spfa;
end;
begin
init;
main;
terminate;
end.