HDU 6741 MUV LUV UNLIMITED (博弈论)

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=6741

题解

看完题解深刻地意识到自己是个智障。

(1) 如果某个叶子节点的父亲有多于一个儿子,则为必胜态。
证明: 设去掉该叶子后为必败态,则直接删去该点先手必胜;若去掉该叶子后为必胜态,则先手将删去该点之后的必胜策略和这个叶子一同删去,依然是必胜策略。

(2) 若不存在一个叶子结点父亲有多于一个儿子,考虑每个叶子(含)到深度最大的儿子个数多于\(1\)的祖先(不含)之间的点数。若所有的这些数都是偶数,那么后手必胜,因为后手可以模仿先手直到存在一个叶子结点父亲有多于一个儿子(也就是某个叶子到深度最大的儿子个数多于\(1\)的祖先只剩\(1\)的距离了),从而达到必胜态。否则先手必胜,因为先手可以一步转换为后手必胜状态。
时间复杂度\(O(n)\).

代码

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define riterator reverse_iterator
using namespace std;

inline int read()
{
    int x=0,f=1; char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-'0';}
    return x*f;
}

const int N = 1e6;
int fa[N+3],sonn[N+3];
int n;

int main()
{
    int T = read();
    while(T--)
    {
        n = read();
        for(int i=2; i<=n; i++) fa[i] = read(),sonn[fa[i]]++;
        bool ans = false;
        for(int i=1; i<=n; i++)
        {
            if(sonn[i]==0)
            {
                if(sonn[fa[i]]>1) {ans = true; break;}
                int cnt = 1; for(int u=i; sonn[fa[u]]==1; u=fa[u]) {cnt++;}
                if(cnt&1) {ans = true; break;}
            }
        }
        if(ans==true) puts("Takeru"); else puts("Meiya");
        for(int i=1; i<=n; i++) fa[i] = sonn[i] = 0;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/suncongbo/p/12199866.html