【NOIP2013模拟11.6A组】摧毁巴士站(bus)
Description
Gabiluso是最伟大的间谍之一。现在,他试图完成一个“不可能完成”的使命――减缓Colugu的军队到达机场的时间。Colugu有n个公共汽车站和m条道路。每条道路直接连接两个巴士站,所有的道路都是单向的。为了保持空气洁净,政府禁止所有军用车辆,因此,军队必须乘搭巴士去机场。两个巴士站之间,可能有超过一条道路。如果一个公共汽车站被破坏时,所有连接该站的道路将无法运作。Gabiluso需要做的是摧毁了一些公共汽车站,使军队无法在K分钟内到达机场。一辆公交车通过一条道路,都是一分钟。所有巴士站的编号从1到n。1号巴士站是在军营,第n号站是机场。军队始终从第一站出发。第一站和第n站不能被破坏,这里有大量的防御力量。当然也没有从第一站到第n站的道路。
请帮助Gabiluso来计算能完成使命所需摧毁的最低数目的巴士站。
Input
第一行包含三个整数n,m,k
接下来m行,每行2个整数s和f,表示从站s到站f有一条路。
Output
输出最少需要摧毁的巴士站数目。
Sample Input
5 7 3
1 3
3 4
4 5
1 2
2 5
1 4
4 5
Sample Output
2
题解:本题还是十分有含金量的题目,用爆搜会时超,加最短路,才AC(听说可以用网络流)具体做法就是——
可以递归摧毁哪个点,然后最短路判断。但是有些点,可能经过他的路径,长度都是大于k的,那么这些点就不必要进行递归。于是,我们每次找一次最短路,看看从1~n的最短路分别经过了哪几个点。因为这里面的点都是在不符合条件的最短路里,所以我们递归那些经过的点删或者不删,直到最短路符合k的条件为止,去一个删的数目最少的为答案即可。 存最短路径是一条怎样的路,可以用s[x]表示更新x这个点,最后是哪个点更新的,即可。
标程:
var
ans,head,tail,n,m,i,j,k,l,u,v,x,y:longint;
t,dist,zt:array[0..101]of longint;
map:array[0..101,0..101]of longint;
bz,bz1:array[0..101]of boolean;
procedure spfa;
begin
fillchar(bz1,sizeof(bz1),false);
fillchar(dist,sizeof(dist),127);
fillchar(zt,sizeof(zt),0);
fillchar(t,sizeof(t),0);
dist[1]:=0;
t[1]:=1;
head:=0;
tail:=1;
bz1[1]:=true;
repeat
inc(head);
u:=t[head];
bz1[u]:=false;
for v:=1 to n do
begin
if(bz[v])and(map[u,v]>0)and(dist[v]>dist[u]+map[u,v])then
begin
dist[v]:=dist[u]+map[u,v];
zt[v]:=u;
if bz1[v]=false then
begin
inc(tail);
t[tail]:=v;
bz1[v]:=true;
end;
end;
end;
until head>=tail;
end;
procedure dg(dep:longint);
var
i,j,l:longint;
q:array[0..101] of longint;
begin
if dep>ans then exit;
spfa;
if dist[n]>k then
begin
if dep<ans then ans:=dep;
exit;
end
else
begin
l:=dist[n]+1;
q[l]:=n;
while zt[q[l]]>0 do
begin
dec(l);
q[l]:=zt[q[l+1]];
end;
for i:=2 to dist[n] do
begin
bz[q[i]]:=false;
dg(dep+1);
bz[q[i]]:=true;
end;
end;
end;
begin
assign(input,'bus.in');reset(input);
assign(output,'bus.out');rewrite(output);
fillchar(bz,sizeof(bz),true);
readln(n,m,k);
for i:=1 to m do
begin
readln(x,y);
if map[x,y]=0 then
inc(map[x,y]);
end;
ans:=maxlongint;
dg(0);
writeln(ans);
close(input);close(output);
end.