2017国家集训队作业[agc014d]Black and White Tree
题意:
有一颗n个点的树,刚开始每个点都没有颜色。Alice和Bob会轮流对这棵树的一个点涂色,Alice涂白,Bob涂黑,Alice先手。若最后存在一个白点,使得这个白点所有相邻点都为白色,则Alice胜,否则Bob胜。请问是先手必胜还是后手必胜。(点数(Nle10^5))
题解:
显然先手使用贪心的策略,使后手被迫操作。(别听这个沙茶,他推了半小时才发现)观察发现若一个点有多个儿子是叶子节点,此时先手必胜,若它只有一个叶子节点儿子,那么选这个点,后手就必选这个叶子。则,在dfs时,若当前点满足上述,则它与它的父亲那条边就可以无视了,这个操作是可以递归的。简单的树形DP。(别听这个沙茶,他没过了拍,却没过样例就交了)%#%q(%w#)#%$^%#%!!!!!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define of(i,l,r) for(int i=l;i>=r;i--)
#define fe(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
inline int rd()
{
static int x,f;
x=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
const int N=100010;
struct edge{
int v,next;
edge(int v=0,int next=0):v(v),next(next){}
}e[N<<1];
int n,siz;
int tot=0,head[N];
bool stp=0,vis[N];
inline void add(int u,int v){e[++tot]=edge(v,head[u]);head[u]=tot;}
inline void dfs(int u,int fat)
{
int cnt=0;vis[u]=1;
fe(i,u){
int v=e[i].v;
if(v==fat)continue;
dfs(v,u);if(stp)return;
if(vis[v])cnt++;
}
if(cnt==1)vis[u]=0,siz-=2;
if(cnt>1||siz==1)stp=1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
n=rd();siz=n;
fo(i,2,n){
int x=rd(),y=rd();
add(x,y);add(y,x);
}
dfs(1,0);
if(stp)puts("First");
else puts("Second");
return 0;
}
我是真滴菜