2018 牛客国庆集训派对Day4 - H 树链博弈

链接:https://ac.nowcoder.com/acm/contest/204/H
来源:牛客网

题目描述

给定一棵 n 个点的树,其中 1 号结点是根,每个结点要么是黑色要么是白色
现在小 Bo 和小 Biao 要进行博弈,他们两轮流操作,每次选择一个黑色的结点将它变白,之后可以选择任意多个(可以不选)该点的祖先(不包含自己),然后将这些点的颜色翻转,不能进行操作的人输
由于小 Bo 猜拳经常输给小 Biao,他想在这个游戏上扳回一城,现在他想问你给定了一个初始局面,是先手必胜还是后手必胜

输入描述:

第一行一个正整数 n
第二行 n 个整数 w
1
..w
n
,w
i
∈ {0,1},w
i
=1 表示第 i 个结点一开始是黑点,否则是白点
接下来 n-1 行,每行两个正整数 u,v 表示一条树边 (u,v)

输出描述:

如果先手必胜,输出First ,否则输出Second
示例1

输入

复制
2
1 0
1 2

输出

复制
First

备注:

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

 



posted @ 2019-09-25 16:41  StarHai  阅读(381)  评论(0编辑  收藏  举报