zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 017D (AGC017D) Game on Tree 博弈

    原文链接https://www.cnblogs.com/zhouzhendong/p/AGC017D.html

    题目传送门 - AGC017D

    题意

      给定一棵 n 个节点的以节点 1 为根的树。

      两个人在博弈,每次可以删除任意一个子树,不能删掉整个树。最终不能操作的人输。

      问先手是否必胜。

      $nleq 10^5$

    题解

      考虑处理出每一个节点的 SG 值。

      对于节点 x ,显然他的所有子树都是独立的,我们只需要求出所有子树的 SG 值然后异或起来就好了。

      假设 y 为 x 的一个儿子,则节点 y 对于 x 的贡献是什么呢?

      显然不是 SG[y] ,因为 x 到 y 还有一条边。在 y 子树中操作的任何时候都可以直接删除这条边到达状态 0 ,相当于 y 子树的所有状态都连了一条到 0 的边。

      所以 SG'[y] = SG[y] + 1 。

      所以 SG[x] 就是所有的 SG'[y] 的异或值(其中 y 为 x 的儿子)。

    代码

    #include <bits/stdc++.h>
    #define y1 __zzd001
    using namespace std;
    typedef long long LL;
    LL read(){
    	LL x=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;
    }
    const int N=100005;
    int n,sg[N];
    vector <int> e[N];
    void solve(int x,int pre){
    	sg[x]=0;
    	for (auto y : e[x])
    		if (y!=pre){
    			solve(y,x);
    			sg[x]^=sg[y]+1;
    		}
    }
    int main(){
    	n=read();
    	for (int i=1;i<n;i++){
    		int x=read(),y=read();
    		e[x].push_back(y);
    		e[y].push_back(x);
    	}
    	solve(1,0);
    	puts(sg[1]?"Alice":"Bob");
    	return 0;
    }
    

      

  • 相关阅读:
    BZOJ 2034 【2009国家集训队】 最大收益
    vijos P1780 【NOIP2012】 开车旅行
    BZOJ 2115 【WC2011】 Xor
    BZOJ 3631 【JLOI2014】 松鼠的新家
    BZOJ 4717 改装
    BZOJ 2957 楼房重建
    BZOJ 4034 【HAOI2015】 T2
    BZOJ 1834 【ZJOI2010】 network 网络扩容
    BZOJ 2440 【中山市选2011】 完全平方数
    BZOJ 2733 【HNOI2012】 永无乡
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/AGC017D.html
Copyright © 2011-2022 走看看