2019CCPC秦皇岛 K MUV LUV UNLIMITED(思维博弈)

2019CCPC秦皇岛K

这个题感觉就是头脑风暴吧,关键在于抓住正确的方向想下去,我中间也跑偏了几次。。。

定义一个分支为从叶子往根的方向,不存在包含多个子节点的节点序列,即从叶子到包含多个子节点的节点的前一个节点的节点序列。(当然这个分支的定义不是一开始就想到的,而是在慢慢深入思考过程中完善的,先写这个只是为了便于叙述)

首先最重要的一点,可以说是走向正确思路的第一步,如果存在只有一个节点的分支,那么先手必胜。

语言上的证明如下,假设初始局面是去掉其中一个只有一个节点的分支以后的局面:如果该局面是先手必胜的,则说明先手可以到达某个先手必败的局面,而加上一个只有一个节点的分支不影响先手到达原来能到的局面,因此先手必胜;如果该局面是先手必败 的,那么先手可以通过只取这个一个节点的分支到达该局面。因此,如果存在只有一个节点的分支,那么先手必胜。

考虑到这个以后,就可以继续思考。如果不存在只有一个节点的分支,对于两个节点的分支,显然没有人愿意取该分支,因为取了之后就会变成先手必胜的局面,显然如果所有分支节点数都为2,则先手必败。那么可以发现节点数为2的分支其实和0是等价的,因为根本就不会被人取,也就不影响局面。

那么思考3的时候,就会发现,这不就又变成了1的情况,如果把其中一个3的分支先变成2,再通过上述证明存在只有一个节点分支的方法来证明,所以如果存在只有三个节点的分支,则先手必胜。那么4分支和2分支又等价。。。

由上述过程,显然可以归纳一下,只有所有分支全为偶数的时候先手必败,否则必胜。

(PS:我想这题的时候,在思考分支的定义时走了不少弯路QAQ,导致一开始就想到了第一步,但是还是想了一段时间才想到后面的)

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+5;
int t,n,sz[maxn],fa[maxn];
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		memset(sz,0,(n+5)*sizeof(int));
		for(int i=2;i<=n;i++){
			scanf("%d",&fa[i]);
			sz[fa[i]]++;
		}
		bool f=0;
		for(int i=1;i<=n&&!f;i++){
			if(sz[i]==0){
				int u=i,tt=0;
				while(sz[u]<2){
					tt++;
					if(u==1)break;
					u=fa[u];
				}
				if(tt&1) f=1;
			}
		}
		if(f) puts("Takeru");
		else puts("Meiya");
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值