[思维] [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;
}

浙公网安备 33010602011771号