Description
外星人入侵地球。可怕的吃人外星人正在全国各地依次序建立它们的基地。
全国共有N(1≤ N ≤10,000)座城市,城市编号1~N。城市之间有M(0≤ M ≤100,000)条双向道路相连。外星人计划建立A(0≤A≤N)个基地。
你只有在距离当前所有外星人基地至少K(1≤K≤100)单位长度的城市才能得到安全。
所以你必须赶快写一个程序决定走到哪里去。
Input
第1行:4个整数N, M, A, K
接下来M行,每行3个整数T1, T2(1≤T1
Output
共A行,第i行1个整数,表示当外星人建好第i个基地后,距离当前所有基地B1,B2,…,Bi至少K长度的城市的数量。
分析
我们要想到,随着新的基地的加入,最短距离不小于K的顶点数量是单调不增的,而且一个顶点一旦进入最短距离小于K的集合,是不可能再跳出那个集合的。
这样,我们可以维护一个全局变量ans,它的初值是第1次最短路后符合条件的顶点数。
在随后的最短路算法中,只要一个f[i]小于K,就从ans中减1。
这样就可以在每次最短路算法后,直接输出ans得解。
如果ans=0,那不用跑spfa,直接输出0就好了。
代码
const
maxn=20000;
maxe=210000;
type
arr=record
x,y,w:longint;
next:longint;
end;
var
edge:array[1..maxe] of arr;
f:array[1..maxn] of longint;
ls:array[1..maxn] of longint;
ans:array[1..maxn] of boolean;
status:array[1..maxn] of boolean;
queue:array[1..maxe*10] of longint;
n,m,nm:longint;
a,dis:longint;
max:longint;
procedure add(x,y,w:longint);
begin
nm:=nm+1;
edge[nm].x:=x;
edge[nm].y:=y;
edge[nm].w:=w;
edge[nm].next:=ls[x];
ls[x]:=nm;
end;
procedure init;
var
i,j,k:longint;
x,y,w:longint;
begin
readln(n,m,a,dis);
for i:=1 to m do
begin
readln(x,y,w);
add(x,y,w);
add(y,x,w);
end;
end;
procedure spfa(s:longint);
var
i,j,k:longint;
head,tail:longint;
begin
fillchar(f,sizeof(f),$7f);
fillchar(status,sizeof(status),false);
head:=0; tail:=1;
queue[1]:=s;
status[s]:=true;
f[s]:=0;
repeat
head:=head+1;
i:=ls[queue[head]];
while i<>0 do
with edge[i] do
begin
if f[x]+w<f[y]
then
begin
f[y]:=f[x]+w;
if not status[y]
then begin
tail:=tail+1;
queue[tail]:=y;
status[y]:=true;
end;
end;
i:=next;
end;
status[queue[head]]:=false;
until head=tail;
end;
procedure main;
var
i,j,k:longint;
begin
max:=n;
for i:=1 to a do
begin
readln(j);
if max=0
then
begin
writeln(0);
continue;
end;
spfa(j);
for k:=1 to n do
if (ans[k]) or (f[k]<dis)
then
if not ans[k]
then begin
ans[k]:=true;
max:=max-1;
end;
writeln(max);
end;
end;
begin
init;
main;
end.