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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章