2017国家集训队作业[agc014d]Black and White Tree

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

我是真滴菜

原文地址:https://www.cnblogs.com/JackyhhJuRuo/p/9489697.html