2018 牛客国庆集训派对Day4 - H 树链博弈
链接:https://ac.nowcoder.com/acm/contest/204/H
来源:牛客网
题目描述
给定一棵 n 个点的树,其中 1 号结点是根,每个结点要么是黑色要么是白色
现在小 Bo 和小 Biao 要进行博弈,他们两轮流操作,每次选择一个黑色的结点将它变白,之后可以选择任意多个(可以不选)该点的祖先(不包含自己),然后将这些点的颜色翻转,不能进行操作的人输
由于小 Bo 猜拳经常输给小 Biao,他想在这个游戏上扳回一城,现在他想问你给定了一个初始局面,是先手必胜还是后手必胜
现在小 Bo 和小 Biao 要进行博弈,他们两轮流操作,每次选择一个黑色的结点将它变白,之后可以选择任意多个(可以不选)该点的祖先(不包含自己),然后将这些点的颜色翻转,不能进行操作的人输
由于小 Bo 猜拳经常输给小 Biao,他想在这个游戏上扳回一城,现在他想问你给定了一个初始局面,是先手必胜还是后手必胜
输入描述:
第一行一个正整数 n1
第二行 n 个整数 w
..wn
,wi
∈ {0,1},wi
=1 表示第 i 个结点一开始是黑点,否则是白点
接下来 n-1 行,每行两个正整数 u,v 表示一条树边 (u,v)
输出描述:
如果先手必胜,输出First ,否则输出Second
备注:
1≤ n≤ 1000
题解:
首先,每层的黑点数为偶数的时候,为先手必败态。首先,没有黑点,都是0,肯定是先手必败态。
当每层的黑点数为偶数时,A先手,他把一个黑点变为白色时(假设不动它的祖先们的颜色),B把同层的另一个黑点变为白色,就回到了每层的黑点数为偶数的时候(即先手必败态)。
如果他把一些祖先们的颜色变了,我们还是可以同层的另一个黑点变为白色,然后把变化的祖先层(此时黑点数肯定为奇数),变化一下,把黑变白,或者白变黑,黑点数又回偶数了。
先手必胜态(每层的黑点数不都为偶数)一定能转化为先手必败态(每层的黑点数为偶数)。
先手必败态只能到先手必胜态。
参考代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1010; int n,w[maxn],cnt[maxn]; vector<int> g[maxn]; void dfs(int u,int fa,int dep) { if(w[u]) cnt[dep]++; for(int i=0,len=g[u].size();i<len;++i) { int v=g[u][i]; if(v==fa) continue; dfs(v,u,dep+1); } } int main() { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",w+i); for(int i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs(1,0,1); bool flag=false; for(int i=1;i<=n;++i) if(cnt[i]&1) flag=true; if(flag) puts("First"); else puts("Second"); return 0; }