jzoj P1350 游戏___dfs+树的深度

题目大意:

BAlice有M1块石子,Bob有M2块石子,游戏一开始,所有石头放在树的节点处,除了树根。Alice先移然后两人轮流移动,每次移动只能选择自己的一个石子,而且只能从当前位置移到父亲节点处,游戏过程中允许一个节点处放多个石子。
谁先把自己所有的石子移到树根处谁就失败了,假设两人都是非常聪明,游戏过程中都使用最优策略,给定石子起始位置,要你计算出谁是赢家。

有T组询问 T<=10
树的节点数为N
1<=N<=10000
1<=M1<=10000
1<=M2<=10000
注意0是树根

题解:

这题其实不是想象中的博弈,而是一道比较简单的题目。
不难发现,只要将双方所有石子走到根节点0的路径和求出来然后判断即可。
首先可以弄双向边,然后以0为根构建一颗树,因为0必定为树根(题意)
然后求出每个点的深度记录一下,对于i点走到根节点的步数,为deep[i]-1
然后枚举所有点算Alice跟Bob分别一共能走多少步

当可行步数相同时因为Alice先手所以Bob胜
否则谁大谁胜

代码:

var
    check,list,deep:array [0..10001] of longint;
    num:array [0..10001,1..2] of longint;
    w,next:array [0..20001] of longint;
    t,p,q,z,i,j,n,m1,m2:longint;

procedure add(x,y:longint);
begin
     inc(z);
     w[z]:=y;
     next[z]:=list[x];
     list[x]:=z;
end;

procedure dfs(now,dep:longint);
var
     i:longint;
begin
     deep[dep]:=now;
     i:=list[dep];
     while i>0 do
        begin
            if check[w[i]]=-1 then
            begin
                 check[w[i]]:=-5;
                 dfs(now+1,w[i]);
            end;
            i:=next[i];
        end;
end;

begin
      readln(t);
      while t>=1 do
         begin
              readln(n,m1,m2);
              z:=0; 
              for i:=0 to n-1 do
                begin
                     list[i]:=0;
                     check[i]:=-1;
                     deep[i]:=0;
                     num[i,1]:=0;
                     num[i,2]:=0;
                end;

              for i:=1 to n-1 do
                begin
                     readln(p,q);
                     add(p,q);
                     add(q,p);
                end;
              check[0]:=-5;
              dfs(1,0);
              for i:=1 to m1 do
                 begin
                      read(p);
                      inc(num[p,1]);
                 end;
              for i:=1 to m2 do
                 begin
                      read(q);
                      inc(num[q,2]);
                 end;
              p:=0; q:=0;
              for i:=0 to n-1 do
                begin
                    p:=p+(deep[i]-1)*num[i,1];
                    q:=q+(deep[i]-1)*num[i,2];
                end;
              if p>q then writeln('Alice')
                     else writeln('Bob');
              dec(t);
         end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值