Lights
【题目描述】
Spray来到了zz城。这个城市的的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多只有一条直达公路。公路的起止点不会是同一路口。在任意一条公路上顺不同方向走所需时间相同。每一个路口都有交通灯,这些交通灯在某一时刻要么是蓝色,要么是紫色。同一个灯上2个颜色的维持时间受到定期调控,总是蓝色持续一段时间,紫色持续一段时间。交通规则规定两个路口可以通车仅当公路两边交通灯的颜色相同(也就是说只要你在A路口看见A与B的交通灯颜色相同,那么就可以走上A-B这条路并到达B路口)。交通工具可以在路口等候。
现在Spray有这个城市的地图,包含:
·1. 通过所有公路需要的时间(整数)
·2. 每个路口交通灯两种颜色的持续时间(整数)
·3. 每个路口交通灯的初始颜色以及初始颜色的持续时间(整数).
你的任务是帮Spray找到一条从起点到终点的最快路径(保证路径唯一)。【输入数据】
第一行包含两个整数: 起点和终点的编号.
第二行包含两个整数: N, M. (2 ≤ N ≤ 300 ,1 ≤ M ≤ 14000)
接下来 N 行描述 N 个路口的情况.
第i+2行 是 i 号路口的信息: Ci, riC, tiB, tiP 。
其中字符 Ci 要么是“B”代表蓝色,要么是“P”代表紫色,表示 i 的起始颜色. riC, tiB, tiP 分别表示初始颜色,蓝色,紫色的持续时间,
(1 ≤ tiC ≤ 100 . 1 ≤ riC ≤ tiC )
最后的 M 行表示关于 M 条公路的信息。包含: i, j, lij 。i 和 j 号路口被这条路连接. lij 是通过i到j这条公路需要的时间。(1 ≤ lij ≤ 100)
【输出数据】
如果存在最短路径:
第一行输出最短时间。
第二行是一个对应第一行答案的路口编号表,从起点到终点输出路口编号,数字之间用空格隔开(即输出路径方案)。
如果不存在,直接输出“0”。
【样例输入】
1 4
4 5
B 2 16 99
P 6 32 13
P 2 87 4
P 38 96 49
1 2 4
1 3 40
2 3 75
2 4 76
3 4 77
【样例输出】
127
1 2 4
四维 SPFA 。
好理解,不好打。
注意 ci 是初始颜色还需要维持的时间。
program lonely;
const
maxn=10000;
man=1000000000;
type
rec=record
t:array[0..1] of longint;
st,tst:longint;
end;
nod=record
y,len,next:longint;
end;
var
a:array[0..400] of rec;
map:array[0..30000] of nod;
first:array[0..400] of longint;
f,dist:array[0..400] of longint;
v:array[0..400] of boolean;
tot,extra,st,en,head,tail,x,y,len,t,i,n,m:longint;
c:char;
que:array[0..10000] of longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
function can(x,y,time:longint):boolean;
var
ta,tb,tta,ttb:longint;
begin
if (time<a[x].tst)and(time<a[y].tst) then
begin
if a[x].st=a[y].st then exit(true);
ta:=a[x].tst-time;
tb:=a[y].tst-time;
if ta=tb then
begin
if a[x].t[1-a[x].st]=a[y].t[1-a[y].st] then
begin
if a[x].t[a[x].st]=a[y].t[a[y].st] then
extra:=1000000000
else extra:=min(a[x].t[a[x].st],a[y].t[a[y].st])+ta+a[x].t[1-a[x].st];
end
else extra:=min(a[x].t[1-a[x].st],a[y].t[1-a[y].st])+ta;
end
else extra:=min(ta,tb);
exit(false);
end;
if (time>=a[x].tst)and(time<a[y].tst) then
begin
ta:=(time-a[x].tst) mod (a[x].t[1]+a[x].t[0]);
if (ta>a[x].t[1-a[x].st]) then
begin
if a[x].st=a[y].st then exit(true)
else
begin
ta:=a[x].t[1]+a[x].t[0]-ta;
tb:=a[y].tst-time;
if ta=tb then
begin
if a[x].t[1-a[x].st]=a[y].t[1-a[y].st] then
begin
if a[x].t[a[x].st]=a[y].t[a[y].st] then
extra:=1000000000
else extra:=min(a[x].t[a[x].st],a[y].t[a[y].st])+ta+a[x].t[1-a[x].st];
end
else extra:=min(a[x].t[1-a[x].st],a[y].t[1-a[y].st])+ta;
end
else extra:=min(ta,tb);
exit(false);
end;
end
else
begin
if 1-a[x].st=a[y].st then exit(true)
else
begin
ta:=a[x].t[1-a[x].st]-ta;
tb:=a[y].tst-time;
if ta=tb then
begin
if a[x].t[a[x].st]=a[y].t[1-a[y].st] then
begin
if a[x].t[1-a[x].st]=a[y].t[a[y].st] then
extra:=1000000000
else extra:=min(a[x].t[1-a[x].st],a[y].t[a[y].st])+ta+a[x].t[a[x].st];
end
else extra:=min(a[x].t[a[x].st],a[y].t[1-a[y].st])+ta;
end
else extra:=min(ta,tb);
exit(false);
end;
end;
end;
if (time>=a[x].tst)and(time>=a[y].tst) then
begin
ta:=(time-a[x].tst) mod (a[x].t[1]+a[x].t[0]);
tb:=(time-a[y].tst) mod (a[y].t[1]+a[y].t[0]);
if (ta>a[x].t[1-a[x].st]) then
begin
ta:=a[x].t[1]+a[x].t[0]-ta;
tta:=a[x].st
end
else
begin
tta:=1-a[x].st;
ta:=a[x].t[tta]-ta;
end;
if (tb>a[y].t[1-a[y].st]) then
begin
tb:=a[y].t[1]+a[y].t[0]-tb;
ttb:=a[y].st
end
else
begin
ttb:=1-a[y].st;
tb:=a[y].t[ttb]-tb;
end;
if tta=ttb then exit(true)
else
begin
if ta=tb then
begin
if a[x].t[1-tta]=a[y].t[1-ttb] then
begin
if a[x].t[tta]=a[y].t[ttb] then
extra:=1000000000
else extra:=min(a[x].t[tta],a[y].t[ttb])+ta+a[x].t[1-tta];
end
else extra:=min(a[x].t[1-tta],a[y].t[1-ttb])+ta;
end
else extra:=min(ta,tb);
exit(false);
end;
end;
exit(false);
end;
procedure print(x:longint);
begin
if x=0 then exit;
print(f[x]);
write(x,' ');
end;
begin
assign(input,'lights.in');
reset(input);
assign(output,'lights.out');
rewrite(output);
readln(st,en);
readln(n,m);
fillchar(a,sizeof(a),255);
for i:=1 to n do
begin
read(c);
if c='P' then a[i].st:=0 else a[i].st:=1;
read(c);
readln(a[i].tst,a[i].t[1],a[i].t[0]);
end;
tot:=0;
for i:=1 to m do
begin
readln(x,y,len);
inc(tot);
map[tot].y:=y;map[tot].len:=len;
map[tot].next:=first[x];
first[x]:=tot;
inc(tot);
map[tot].y:=x;map[tot].len:=len;
map[tot].next:=first[y];
first[y]:=tot;
end;
for i:=1 to n do dist[i]:=man;
dist[st]:=0;
f[st]:=0;
v[st]:=true;
head:=0;tail:=1;
que[tail]:=st;
while head<>tail do
begin
inc(head);
if head>maxn then head:=1;
x:=que[head];
t:=first[x];
while t<>0 do
begin
y:=map[t].y;
extra:=0;
if (can(x,y,dist[x]))or(can(y,x,dist[x])) then
begin
if dist[x]+map[t].len<dist[y] then
begin
dist[y]:=dist[x]+map[t].len;
f[y]:=x;
if not v[y] then
begin
v[y]:=true;
inc(tail);
if tail>maxn then tail:=1;
que[tail]:=y;
end;
end;
end
else if dist[x]+map[t].len+extra<dist[y] then
begin
dist[y]:=dist[x]+map[t].len+extra;
f[y]:=x;
if not v[y] then
begin
v[y]:=true;
inc(tail);
if tail>maxn then tail:=1;
que[tail]:=y;
end;
end;
t:=map[t].next;
end;
v[x]:=false;
end;
if dist[en]<man then
begin
writeln(dist[en]);
print(f[en]);
writeln(en);
end
else writeln(0);
close(input);
close(output);
end.