[思维] [AGC014D] Black and White Tree

posted on 2024-04-27 06:00:00 | under | source

用的是粉兔的解释,实在是妙。

操作一:先手将叶子的父亲染白,则后手必将该叶子染黑。

操作二:若存在多个叶子有同一个父亲,则先手将该父亲染白,先手必胜。

显然对于叶子来说只有这两种情况了。

我们选取一点 \(u\) 定为根,则会挂着许多子树。

假设下述过程中不存在操作二的情况。那么将该子树一直进行操作一,相当于删掉这两点。若子树大小为奇数,则最后只剩下该子树的根。

所以若 \(u\) 存在两个奇数大小的子树,则最后进行操作二即可做到先手必胜。

注意:因为是假设,所以不会把先手必败的情形判定为必胜。

那么将所有点都定为根判定一次就好了。假如最后没有找到符合要求的根呢?直接认为后手必胜吗?

确实如此。因为上述过程等价于判定是否存在完美匹配,如果有,那么先手每染白后手将其匹配点染黑,最后所有白点必与黑点相邻,后手必胜。

代码

#include<bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;
int n, u, v, siz[N];
vector<int> to[N];

inline bool dfs(int u, int fa){
	bool flag = false; int cnt = 0;
	siz[u] = 1;
	for(auto v : to[u])
		if(v ^ fa) flag |= dfs(v, u), cnt += siz[v] & 1, siz[u] += siz[v];
	cnt += (n - siz[u]) & 1;
	return flag | (cnt >= 2); 
}
int main(){
	cin >> n;
	for(int i = 1; i < n; ++i) scanf("%d%d", &u, &v), to[u].push_back(v), to[v].push_back(u);
	if(dfs(1, 0)) printf("First");
	else printf("Second");
	return 0;
}

posted @ 2026-01-13 11:18  Zwi  阅读(0)  评论(0)    收藏  举报