[agc014d]Black and White Tree

本文探讨了一种博弈问题,即两人轮流为树上的节点染色,先手涂白色,后手涂黑色。若最终存在一个白色节点周围无黑色节点,则先手胜。文章通过分析得出后手要获胜树必须具备完美匹配,并提供了一个算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

看到这种题直觉是树的最大匹配,如果是比赛直接打毫无疑问。
然后证明了一下也不是很难的样子。
主要是见过类似套路吧。

题意

两个人轮流给树上节点染色。
先手涂白色,后手涂黑色。
如果最后树上存在一个白色点,与其相连的没有黑点,先手胜,否则后手胜。
请你判断先手必胜还是后手必胜。

博弈

我们先给出结论:后手要赢,这颗树要有完美匹配。
首先充分性显然,有完美匹配,先手涂什么成白色,你把匹配点涂黑,那么一定任意白点都有相连黑点。
我们来证明必要性吧。
首先找到一个未匹配点,提到根,剩余可以贪心匹配。
然后你先找到一个叶子,其和父亲匹配,且父亲只有它这一个儿子,根据贪心匹配法这个父亲当然和它匹配了(和上面匹配不会更优)。
然后如果你找不到这样的叶子,说明每个叶子的父亲子树都没有完美匹配,直接就完蛋了。然后先手直接涂父亲,就直接获胜了。
否则,先手把父亲涂白,后手必须把这个叶子涂黑,否则先手直接赢了,于是完成了一轮操作,然后我们可以删去这两个点了。
显然这样步步紧逼,后手被我们强迫着动,最后根节点所有儿子一定都染成白了,然后先手再来一下,获胜。
于是我们这题只需要判断树有没有完美匹配,这个贪心即可。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100000+10;
int h[maxn],go[maxn*2],nxt[maxn*2];
int i,j,k,l,t,n,m,tot;
void add(int x,int y){
    go[++tot]=y;
    nxt[tot]=h[x];
    h[x]=tot;
}
int perfect(int x,int y){
    int t=h[x];
    int p=0;
    while (t){
        if (go[t]!=y) p+=perfect(go[t],x);
        t=nxt[t];
    }
    if (p>=2) return p;
    else return p^1;
}
int main(){
    scanf("%d",&n);
    fo(i,1,n-1){
        scanf("%d%d",&j,&k);
        add(j,k);add(k,j);
    }
    if (perfect(1,0)==0) printf("Second\n");
    else printf("First\n");
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值