zoukankan      html  css  js  c++  java
  • AtCoder AGC033C Removing Coins (博弈论)

    题目链接

    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;
    }
    
  • 相关阅读:
    一道题DP
    BZOJ 3155: Preprefix sum
    BZOJ:3209: 花神的数论题
    TJU 4087. box
    BZOJ1192: [HNOI2006]鬼谷子的钱袋
    概率DP
    Codeforces Round #253 (Div. 2) D题
    二维树状数组
    Codeforces Round #250 (Div. 2)
    莫比乌斯函数
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12227637.html
Copyright © 2011-2022 走看看