题意:n个点,编号为0~n-1,m条有向边,限速不为0的边按照限速前进,限速为0的边按进入这条道路时的速度前进(即到该条边起点的速度),给定终点,初始起点为点0,初始速度为70,问从点0到终点最快时间的路径
可以理解成拆点的spfa
dis[i,j]表示到达第i个点的速度为j,spfa更新时讨论该边的速度是否为0分别按两种方法更新,
每次更新dis[i,j]时,记录转移来的点和转移来的速度(注意并不是入队的时候才更新,并且要两个都记录,只记录转移来的点的话会出事情...mdzz)
var
n,m,st,x,y,z,w :longint;
minn,l,tot :longint;
i :longint;
ans :double;
pre,other,len,v :array[0..50010] of longint;
dis :array[0..200,0..510] of double;
vis :array[0..200,0..510] of boolean;
que :array[0..75010,0..1] of longint;
last,way :array[0..200] of longint;
fromn,fromv :array[0..200,0..510] of longint;
procedure connect(x,y,vv,z:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
len[l]:=z;
v[l]:=vv;
end;
procedure spfa;
var
h,tmp,tl,cur,p,q:longint;
begin
fillchar(dis,sizeof(dis),127);
h:=0; tl:=1;
que[1,0]:=1; que[1,1]:=70;
dis[1,70]:=0;
while (h<>tl) do
begin
h:=h mod 75005+1;
cur:=que[h,0]; tmp:=que[h,1];
vis[cur,tmp]:=false;
q:=last[cur];
while (q<>0) do
begin
p:=other[q];
if v[q]=0 then
begin
if dis[p,tmp]>dis[cur,tmp]+len[q]/tmp then
begin
dis[p,tmp]:=dis[cur,tmp]+len[q]/tmp;
fromn[p,tmp]:=cur;
fromv[p,tmp]:=tmp;
if not vis[p,tmp] then
begin
vis[p,tmp]:=true;
tl:=tl mod 75005+1;
que[tl,0]:=p;
que[tl,1]:=tmp;
end;
end;
end else
begin
if dis[p,v[q]]>dis[cur,tmp]+len[q]/v[q] then
begin
dis[p,v[q]]:=dis[cur,tmp]+len[q]/v[q];
fromv[p,v[q]]:=tmp;
fromn[p,v[q]]:=cur;
if not vis[p,v[q]] then
begin
vis[p,v[q]]:=true;
tl:=tl mod 75005+1;
que[tl,0]:=p;
que[tl,1]:=v[q];
end;
end;
end;
q:=pre[q];
end;
end;
end;
procedure print(x,v:longint);
var
y,xx:longint;
i:longint;
begin
tot:=0; xx:=x;
while (x<>-1) do
begin
inc(tot);
way[tot]:=x;
x:=fromn[xx,v];
v:=fromv[xx,v];
xx:=x;
end;
for i:=tot downto 2 do write(way[i]-1,' ');
writeln(way[1]-1);
end;
begin
read(n,m,st); inc(st);
for i:=1 to m do
begin
read(x,y,z,w);
connect(x+1,y+1,z,w);
end;
fillchar(fromn,sizeof(fromn),255);
spfa;
ans:=maxlongint;
for i:=0 to 500 do
if dis[st,i]
——by Eirlys