标签:
题意:有n个点和m条道路。有一些点必须经过了某些点后才能到达,问从起点到达终点的最短时间。
分析:带限制的最短路。
设d1[x]为可以进入点x的时间,d2[x]为到达点x的时间,s[x]为点x被多少个点保护。
一开始以为d1和d2是有关联的,也就是要通过d1来推出某些d2,然后想破脑袋都想不出(其实也没那么夸张啦)。后来看了题解才发现这两个可以分开求,然后进入点x的实际时间为max(d1[x],d2[x])。
然后跑dijkstra,每次找到一个d2最小且s[x]=0的点,然后更新与这个点相连的点和被这个点保护的城市dec(s).
代码:
const
maxn=3007;
maxm=70007;
var
n,m,e:longint;
last,s,last1:array[1..maxn] of longint;
d1,d2:array[1..maxn] of int64;
side:array[1..maxm*15] of record
x,y,z,next:longint;
end;
v:array[1..maxn] of boolean;
procedure add(x,y,z:longint);
begin
inc(e);
side[e].x:=x; side[e].y:=y; side[e].z:=z;
side[e].next:=last[x]; last[x]:=e;
end;
procedure add1(x,y:longint);
begin
inc(e);
side[e].x:=x; side[e].y:=y;
side[e].next:=last1[x]; last1[x]:=e;
end;
procedure init;
var
x,y,z,i,j:longint;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y,z);
add(x,y,z);
end;
for i:=1 to n do
begin
read(s[i]);
for j:=1 to s[i] do
begin
read(y);
add1(y,i);
end;
if s[i]>0 then d1[i]:=1 shl 62;
end;
end;
function max(x,y:int64):int64;
begin
if x>y then exit(x)
else exit(y);
end;
procedure dij;
var
u,i:longint;
min,w:int64;
begin
for i:=2 to n do
d2[i]:=1 shl 62;
fillchar(v,sizeof(v),true);
repeat
min:=1 shl 62;
u:=0;
for i:=1 to n do
if (v[i])and(d2[i]<min)and(s[i]=0) then
begin
min:=d2[i];
u:=i;
end;
if u>0 then
begin
w:=max(d1[u],d2[u]);
v[u]:=false;
i:=last[u];
while i>0 do
with side[i] do
begin
if (w+z<d2[y])and(v[y]) then d2[y]:=w+z;
i:=next;
end;
i:=last1[u];
while i>0 do
with side[i] do
begin
dec(s[y]);
if s[y]=0 then d1[y]:=w;
i:=next;
end;
end;
until u=0;
writeln(max(d1[n],d2[n]));
end;
begin
init;
dij;
end.
bzoj 1922: [Sdoi2010]大陆争霸 带限制最短路
标签:
原文地址:http://blog.csdn.net/qq_33229466/article/details/51367039