题目
背景 Background
这次小杉来到了经典美剧《越狱》的场景里……
他被抓起来了(-.-干嘛幻想这么郁闷的场景……)。
小杉身为新一代的Scofield,在挖了半个月之后终于挖通牢房里的地道。
在地道里,无数的管道路线困惑了他。
(若对情节有任何疑问,请观看原剧)
描述Description
小杉看了看自己的纹身,明白了整个管道网是由N个小房间和若干小房间之间的单向的管道组成的。
小房间编号为不超过N的正整数。
每个管道都有一个人品限制值,小杉只能在人品不超过该限制值时通过。
小杉一开始在房间1,现在小杉想知道,每个小房间他最多能够以人品多少的状态到达。
注意,小杉的人品在出发以后是不会改变的。
第一行有一个正整数N(1<=N<=2000)。
接下来若干行描述管道,每行三个正整数A,B,R(1<=A,B<=N,1<=R<1e5,A!=B),表示A房间有一条到达B房间的人品限制值为R的管道(注意从B房间不可由此管道到达A房间,即管道是单向的,每组A,B至多只出现一次)。
整个输入数据以一行000结束。
对每组测试数据输出N-1行,分别表示对于2到N号的小房间,小杉最多能够以人品多少的状态到达。若某房间小杉不能到达,请输出0。
4
1 2 30
1 3 20
2 3 25
3 4 30
2 4 20
0 0 0
30
25
25
注释Hint
对于样例数据:
小杉最多能够在人品为30的情况下到达小房间2(1->2)
小杉最多能够在人品为25的情况下到达小房间3(1->2->3)
小杉最多能够在人品为25的情况下到达小房间4(1->2->3->4)
题解
很显然是最短路,我打了一个SPFA
和普通的SPFA不同的地方在于
if d[x]+w[k]<d[y] then
换成了
if min(d[v[(h-1) mod max+1]],w[k])>d[y[k]] then
刚开始担心爆内存,算了老半天,省了所有能省的内存,结果没爆,其实就算不省也不会爆……
longint 4字节 int64 8字节
代码
const
max=2000;
var
n,i,j,k,t:longint;
w:array[1..4000000]of longint;
y,ne:array[1..4000000]of integer;
d,ls:array[1..2000]of longint;
b:array[1..2000]of boolean;
v:array[1..2000]of longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
procedure spfa;
var
i,j,k,h,t:longint;
begin
fillchar(b,sizeof(b),true);
h:=0;t:=1;v[1]:=1;b[1]:=false;d[1]:=maxlongint;
while h<t do
begin
inc(h);
k:=ls[v[(h-1) mod max+1]];
while k>0 do
begin
if min(d[v[(h-1) mod max+1]],w[k])>d[y[k]] then
begin
d[y[k]]:=min(d[v[(h-1) mod max+1]],w[k]);
if b[y[k]] then
begin
b[y[k]]:=false;
inc(t);
v[(t-1) mod max+1]:=y[k];
end;
end;
k:=ne[k];
end;
b[v[(h-1) mod max+1]]:=true;
end;
end;
begin
readln(n);
readln(i,j,k);
while (i<>0)and(j<>0)and(k<>0)do
begin
if j=1 then begin readln(i,j,k);continue;end;
inc(t);
y[t]:=j;w[t]:=k;ne[t]:=ls[i];
ls[i]:=t;
readln(i,j,k);
end;
spfa;
for i:=2 to n do
writeln(d[i]);
end.