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;
    }
    

      

  • 相关阅读:
    hdu 3951 Coin Game
    hdu 1273 漫步森林
    hdu 2082 找单词
    kmp算法(模板)
    CodeForces 742B Arpa’s obvious problem and Mehrdad’s terrible solution
    大二上每日总结
    大二上每日总结
    大二上每日总结
    大二上学期周总结
    大二上每日总结
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/AGC017D.html
Copyright © 2011-2022 走看看