题意: 两个人玩游戏, 有一棵有根树,每次只能拿叶子节点若干个(不能不拿),问最后谁会赢
思路:
先说结论,数每个叶子节点对应上去的那条链(直到他的父亲除自己外有另外的儿子结束)的节点个数(称为树枝),如果存在奇数,则先手必胜,否则,先手必败。
简单证明一下
首先,如果树枝的节点个数为1,那么如果我拿掉这个节点之后是必败态,我就可以直接拿掉这个节点,使对手进入必败态。如果是必胜态,那就说明先手可以通过拿一些节点到达必败态,则我现在就可以拿掉那些节点,然后多拿这个节点,则现在的局面一定是必败态。
综上,如果存在树枝节点个数为1的,那么先手必胜。
1可以推广到奇数,即:先手可以把所有节点个数为奇数的树枝的叶子节点拿掉,使它变成偶数,这样对手只能把一些偶数给破坏掉,然后我一直把奇数变成偶数,这样就可以熬到对手把某个树枝的节点个数变成1,就变成了上一个状态,先手就必胜了。
代码:
#include<bits/stdc++.h>
#define endl "\n"
// #define int long long
// #define x first
// #define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10, mod = 1e9 + 7, inf = 1e18;
const double eps = 1e-9, pi = acos(-1);
int n, m;
vector<int> g[N];
int fa[N];
int dfs(int u, int pre){
bool flag = 1;
for(int i = 0; i < g[u].size(); i ++){
int j = g[u][i];
if(j == pre) continue;
fa[j] = u;
flag = 0;
if(dfs(j, u)) return 1;
}
if(flag){
int p = u;
int cnt = 1;
while(p != 1){
p = fa[p], cnt ++;
if(g[p].size() > 1){
if(cnt & 1) return 0;
else return 1;
}
}
if(p == 1) return cnt & 1;
}
return 0;
}
void solve()
{
cin >> n;
for(int i = 1; i <= n; i ++) g[i].clear(), fa[i] = 0;
for(int i = 2; i <= n; i ++){
int x;
cin >> x;
g[x].push_back(i);
}
cout << (dfs(1, -1) ? "Takeru\n" : "Meiya\n");
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
cin >> T;
while(T -- ) solve();
}