第四题

题目描述
 “尼伯龙根是一棵由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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值