zoukankan      html  css  js  c++  java
  • AGC017D Game on Tree(树型博弈)

    题目大意:

    给出一棵n个结点的树,以1为根,每次可以切掉除1外的任意一棵子树,最后不能切的话就为负,问是先手必胜还是后手必胜。

    题解:

    首先我们考虑利用SG函数解决这个问题

    如果1结点有多个子节点,那么SG[1]显然就是子节点代表的子树的SG[x]异或和

    所以我们就可以把子树全部拆开

    问题就变成了多个树,每个树的根节点只有一个孩子

    这种情况的SG[1]就等于它的孩子SG[x] + 1

    证明如下

    1、切掉孩子,那么SG[x] = 0,说明SG[1]大于0

    2、切掉其他结点,局面变成[切掉结点的部分]加上[根节点连向孩子的一条边],也就是说当前局面的SG值必定大于[切掉结点的部分]的SG值,而SG值的定义又取最小,所以SG[1] = SG[x] + 1

    然后dfs一遍就可以了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    const int maxn = 1e5 +100;
    vector<int> G[maxn];
    int sg[maxn];
    void dfs(int x, int fa){
        sg[x] = 0;
        for(auto to : G[x]){
            if(to == fa) continue;
            dfs(to, x);
            sg[x] ^= (sg[to]+1);
        }
    }
    
    int main()
    {
        int n, x, y;
        cin>>n;
        for(int i = 1; i < n; i++){
            scanf("%d %d", &x, &y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1, 1);
        if(sg[1]) cout<<"Alice";
        else cout<<"Bob";
    }
  • 相关阅读:
    Linux记录-批量安装zabbix(转载)
    k8s-基础环境配置(六)
    k8s记录-ntpd时间同步配置(五)
    k8s记录-flanneld+docker网络部署(四)
    Java面试通关要点汇总集
    Java并发编程系列
    码农需要知道的“潜规则”
    领域驱动设计文章
    自动化测试的一些思考
    轻量级爬虫框架
  • 原文地址:https://www.cnblogs.com/Saurus/p/7208361.html
Copyright © 2011-2022 走看看