我是靠谱客的博主 活泼酒窝,最近开发中收集的这篇文章主要介绍AtCoder Grand Contest 014 D - Black and White Tree 博弈论题意分析代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题意

给你一棵树,先手后手轮流操作,每次先手可以把某个未染色节点染白,后手可以把某个未染色节点染黑。等没有未染色节点时,所有与黑点相邻的白色点都会变黑,若仍存在白点,则先手胜,反之则后手胜。
n<=100000

分析

结论:若存在完美匹配的后手必胜,否则先手必胜。
证明:若存在完美匹配,无论先手染哪一个点,后手必然可以染该点的匹配点,从而后手必胜。
若不存在完美匹配,则必然有至少一个叶节点存在于最大匹配中。先手可以每次找一个存在于最大匹配中的叶节点,将其相邻节点染白,则黑点必然只能染该叶节点。因为没有完美匹配,所以到最后必然会剩下至少一个未匹配点,满足其相邻节点都被染成了白色且当前先手操作。所以先手必胜。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=100005;

int n,cnt,last[N],f[N],g[N];
struct edge{int to,next;}e[N*2];

int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void addedge(int u,int v)
{
    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}

void dp(int x,int fa)
{
    int mx=-n;
    for (int i=last[x];i;i=e[i].next)
    {
        if (e[i].to==fa) continue;
        dp(e[i].to,x);
        g[x]+=max(g[e[i].to],f[e[i].to]);
        mx=max(mx,g[e[i].to]-f[e[i].to]);
    }
    if (mx>=0) f[x]=g[x]+1;
    else if (mx>-n) f[x]=g[x]+mx+1;
}

int main()
{
    n=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read();
        addedge(x,y);
    }
    dp(1,0);
    if (max(f[1],g[1])==n/2&&!(n&1)) puts("Second");
    else puts("First");
    return 0;
}

最后

以上就是活泼酒窝为你收集整理的AtCoder Grand Contest 014 D - Black and White Tree 博弈论题意分析代码的全部内容,希望文章能够帮你解决AtCoder Grand Contest 014 D - Black and White Tree 博弈论题意分析代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部