您的位置:首页 > 其它

第四题

2017-07-17 13:15 60 查看

【2017.7.10普及】第四题 (File IO): input:h3.in output:h3.out

题目描述

 “尼伯龙根是一棵由n-1条高架路连起n 个地区的树,每一次Load,你都会重生在某一个地区。如果重生点是整个尼伯龙根的重心,也就是这个树的重心,那么你就能在最短时间内带诺诺逃脱啦。”“对了,再给你一点方便咯,你可以选一条高架桥断掉,再连接另外两个地方,每次Load只能用一次技能,而又必须使整个它仍构成树形结构。你的Save点在这里,Load自然会恢复原始的尼伯龙根咯。” 

输入

第一行两个整数n,m,n意义如题,m表示路明非Load了m次。接下来n-1行,每行两个整数x,y表示节点x,y之间存在一条边。接下来m行,每行一个整数p,表示这次Load的重生地区。

输出

对于每一个询问,输出一行如果可以则输出”YES”,否则输出”NO”(注意没有引号)

样例输入

5 3
1 2
1 3
1 4
1 5
1
2
3

样例输出

YES
NO
NO

数据范围限制

对于20%的数据 1<=n,m<=50对于50%的数据 1<=n,m<=3000对于100%的数据 1<=n,m<=200000对于此题,只能说不是很难。要搞懂还是很容易的。就是先将这一棵树的重心求出来(找其中一个就好了).用这个点为根重新组装一棵树。我们知道,一棵树的重心的分支上的结点多不会超过N/2。所以,我们可以运用这一特点,当要将一架桥换掉的时候,他的下面结点的是一定不会超过N/2。我们只需要考虑他的上面结点。对于根,他的所有结点数都不会超过N/2,所以,当重组树的根节点不再根的最大结点数的分支中时,我们可以将最大分支直接连到当前根的位置上,这样可以保证剩下的那个边上的结点一定是最小的了;如果在最大结点数的分支中时,取次大的即可。如果剩下的那条边的结点数还是超过了N/2,那么就输出'NO',反之输出'YES'.代码如下:
var
jl,s,g,a,f,x,y:array[1..400000] of longint;
n,m,dian,i,p,ji,max,max2,jis,ans:longint;
h:array[1..400000,1..100] of longint;
bz,zhi:array[1..400000] of boolean;
bo:boolean;
procedure dg(k:longint);
var
i,p:longint;
begin
if k=12 then
k:=k;
for i:=1 to g[k] do
begin
p:=h[k,i];
if bz[p]=false then
begin
bz[p]:=true;
dg(p);
f[k]:=f[k]+f[p];
end;
end;
f[k]:=f[k]+1;
end;
procedure dg2(k:longint);
var
i,p,t,s:longint;
begin
s:=n-f[k];
if bo then
exit;
dec(s);
for i:=1 to g[k] do
begin
p:=h[k,i];
if bz[p] then
continue;
if s<f[p] then
s:=f[p];
end;
if s<=n div 2 then
begin
bo:=true;
dian:=k;
exit;
end
else
begin
for i:=1 to g[k] do
begin
if bz[h[k,i]] then
continue;
bz[h[k,i]]:=true;
dg2(h[k,i]);
if bo then
exit;
end;
end;
end;
procedure jilu(k:longint);
var
i,p:longint;
begin
zhi[k]:=true;
for i:=1 to g[k] do
begin
p:=h[k,i];
if bz[p]=false then
begin
bz[p]:=true;
jilu(p);
end;
end;
end;
begin
assign(input,'h3.in');
assign(output,'h3.out');
reset(input);
rewrite(output);
read(n,m);
for i:=1 to n-1  do
begin
read(x[i],y[i]);
inc(g[x[i]]);
h[x[i],g[x[i]]]:=y[i];
inc(g[y[i]]);
h[y[i],g[y[i]]]:=x[i];
end;
for i:=1 to m do
read(a[i]);
fillchar(bz,sizeof(bz),false);
fillchar(f,sizeof(f),0);
bz[x[1]]:=true;
dg(x[1]);
fillchar(bz,sizeof(bz),false);
bo:=false;
bz[x[1]]:=true;
dg2(x[1]);
fillchar(f,sizeof(f),0);
fillchar(bz,sizeof(bz),false);
bz[dian]:=true;
dg(dian);
for i:=1 to g[dian] do
begin
p:=h[dian,i];
if max<f[p] then
begin
max:=f[p];
ji:=p;
jis:=i;
end;
end;
fillchar(bz,sizeof(bz),false);
fillchar(zhi,sizeof(zhi),false);
bz[dian]:=true;
bz[ji]:=true;
ans:=1;
jilu(ji);
for i:=1 to g[dian] do
if i<>jis then
begin
p:=h[dian,i];
if max2<f[p] then
max2:=f[p];
end;

for i:=1 to m do
begin
if a[i]=dian then
begin
writeln('YES');
continue;
end;
if (zhi[a[i]]) then
begin
if n-f[a[i]]-max2<=n div 2 then
writeln('YES')
else
writeln('NO');
end
else
begin
if n-f[a[i]]-max<=n div 2 then
writeln('YES')
else
writeln('NO');
end;
end;
close(input);
close(output);
end.

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: