Description
有一棵树和两个玩家A、B轮流操作
A先手,每次A可以把一个未染色节点染白,B可以染黑
所有人操作完后,黑色点周围的白点都会变黑,但是新变黑的点不会造成任何影响
若一棵树全变黑了B赢,否则A赢
给出树,问谁能赢
Solution
之前好像见过这个结论
若存在完美匹配,无论先手染哪一个点,后手必然可以染该点的匹配点,从而后手必胜。
若不存在完美匹配,则必然有至少一个叶节点存在于最大匹配中。先手可以每次找一个存在于最大匹配中的叶节点,将其相邻节点染白,则黑点必然只能染该叶节点。因为没有完美匹配,所以到最后必然会剩下至少一个未匹配点,满足其相邻节点都被染成了白色且当前先手操作。所以先手必胜。
然后树的匹配的话上一个树形dp就可以了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int INF=0x3f3f3f3f;
const int N=200005;
struct edge {int x,y,next;} e[N*2];
int f[N],g[N],ls[N],edCnt;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {y,x,ls[y]}; ls[y]=edCnt;
}
void dfs(int x,int fa) {
int rec=-INF,flag=0,wjp=0;
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y==fa) continue;
dfs(e[i].y,x); wjp=1;
int mx=std:: max(g[e[i].y],f[e[i].y]);
g[x]+=mx; f[x]+=mx;
if (mx==g[e[i].y]) flag=1;
rec=std:: max(rec,g[e[i].y]-f[e[i].y]);
}
if (wjp&&!flag||rec+1>0) f[x]+=rec+1;
}
int main(void) {
freopen("data.in","r",stdin);
int n=read();
rep(i,2,n) add_edge(read(),read());
dfs(1,0);
if (std:: max(f[1],g[1])*2==n) puts("Second");
else puts("First");
return 0;
}