AtCoder Grand Contest 017 D - Game on Tree SG函数
2018-02-03 10:01
441 查看
题意
有一棵以1为根的树,两个人在上面玩游戏。每次可以选择一棵子树删掉,不能操作者输。问先手必胜还是后手必胜。n<=100000
分析
我们可以把一棵树拆成若干棵由子树加一个根组成的树,不难发现这和原游戏是等价的。那么原游戏的SG值就等于所有新游戏SG值得异或和。考虑如何求一棵树加上一个根这样一个游戏的SG值。
不难发现原来的每一个状态都可以通过删掉新边来到达SG值为0的状态,也就是原来的DAG,其每个节点都向一个SG值为0的点连了一条边。不难发现这会使原来每个节点的SG值都增加1。
于是新树的SG值就等于原来的SG值+1。
然后就可以做了。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=100005; int n,cnt,last ,sg ; struct edge{int to,next;}e[N*2]; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void addedge(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } void dfs(int x,int fa) { for (int i=last[x];i;i=e[i].next) { if (e[i].to==fa) continue; dfs(e[i].to,x); sg[x]^=sg[e[i].to]+1; } } int main() { n=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y); } dfs(1,0); if (sg[1]) puts("Alice"); else puts("Bob"); return 0; }
相关文章推荐
- AtCoder Grand Contest 017 迟到记
- [AtCoder Grand Contest 017] F: Zigzag (agc017F)
- AtCoder Grand Contest 017-A - Biscuits
- AtCoder Grand Contest 017-B - Moderate Differences
- AtCoder Grand Contest 017 F - Zigzag 状压dp
- AtCoder Grand Contest 017 A
- AtCoder Grand Contest 017 B
- AtCoder Grand Contest 017
- AtCoder Grand Contest 017 题解
- AtCoder Grand Contest 017 D - Game on Tree
- AtCoder Grand Contest 017-A Biscuits
- Atcoder Grand Contest 017 F Zigzag
- AtCoder Grand Contest 017 C - Snuke and Spells
- AtCoder Grand Contest 019 B - Reverse and Compare
- AtCoder Grand Contest 020 B - Ice Rink Game(贪心+计算机乘法)
- AtCoder Grand Contest 014 D - Black and White Tree 博弈论
- AtCoder Grand Contest 016 E - Poor Turkeys 贪心
- AtCoder Grand Contest 009 B - Tournament 贪心
- AtCoder Grand Contest 004 D - Teleporter 贪心
- AtCoder Grand Contest 006 E - Rotate 3x3 树状数组