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;
}
原文地址:https://www.cnblogs.com/suncongbo/p/12199866.html