AtCoder AGC033C Removing Coins (博弈论)

本文解析了一道AtCoder竞赛题目,通过分析树的直径变化,将问题转化为Bash博弈模型。当树的直径长度模3等于2时,后手玩家获胜,反之先手获胜。代码实现使用深度优先搜索计算直径。

题目链接

https://atcoder.jp/contests/agc033/tasks/agc033_c

题解

终于会做点最简单的博弈论了……
首先题目中操作的含义就是选定一个点,把所有不是这个点的叶子删掉(如果这个点不是叶子就删所有叶子)。
对于任何一棵点数不少于\(3\)的树,一定存在一个点(比如非叶子节点),使得对该点操作之后直径减少\(2\);同时一定存在一个点(比如直径的端点),使得对该点操作后直径减少\(1\);同时不存在任何一种操作使得直径发生其他的变化。因此这是一个Bash博弈的模型,答案与直径长度模\(3\)的值有关。
设直径长度(点数)为\(l\). 若\(l=1\)则先手必胜,\(l=2\)则后手必胜。后面就变成了刚才讨论的情况,因此当且仅当直径长度\(\mod 3=2\)时后手必胜。
时间复杂度\(O(n)\).

代码

#include<bits/stdc++.h>
#define llong long long
using namespace std;

inline int read()
{
    int x = 0,f = 1; char ch = getchar();
    for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    return x*f;
}

const int N = 2e5;
struct Edge
{
    int v,nxt;
} e[(N<<1)+3];
int fe[N+3];
int fa[N+3];
int len[N+3];
int n,en,mx;

void addedge(int u,int v)
{
    en++; e[en].v = v;
    e[en].nxt = fe[u]; fe[u] = en;
}

void dfs(int u)
{
    for(int i=fe[u]; i; i=e[i].nxt)
    {
        int v = e[i].v; if(v==fa[u]) continue;
        fa[v] = u; dfs(v);
        mx = max(mx,len[u]+len[v]+1);
        len[u] = max(len[u],len[v]+1);
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1; i<n; i++) {int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u);}
    dfs(1);
    if(mx%3==1) {puts("Second");}
    else {puts("First");}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值