• [atAGC017D]Game on Tree


    将其1为根建树,操作显然即去掉一棵子树(非本身)

    考虑sg函数,定义$sg(T)$为有根树$T$的sg值,则有以下结论——

    结论:令$T'$为$T$的根节点新增一个父亲得到的树,则$sg(T')=sg(T)+1$

    假设去掉$T$任意一棵子树(非本身)后会得到$T_{1},T_{2},...,T_{k}$,$T'_{i}$为$T_{i}$的根节点新增一个父亲得到的树,那么$T'$去掉任意一棵子树(非本身)后即会得到$T'_{1},T'_{2},...,T'_{k}$和"一个节点"的树

    显然"一个节点"的树的$sg$值为0,因此$sg(T')=mex(\{sg(T'_{i}),0\})$

    考虑归纳,并代入$sg(T'_{i})=sg(T_{i})+1$,不难得到$sg(T')=sg(T)+1$,即得证

    进一步的,考虑$T$根节点儿子的子树依次为$T_{1},T_{2},...,T_{k}$,显然对$T_{i}$再加上$T$根节点即是一个独立的问题,结合sg函数的性质和结论,也即$sg(T)=\bigoplus_{i=1}^{k}(sg(T_{i})+1)$,再树形dp即可

    时间复杂度为$o(n)$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 vector<int>v[N];
     5 int n,x,y,sg[N];
     6 void dfs(int k,int fa){
     7     for(int i=0;i<v[k].size();i++)
     8         if (v[k][i]!=fa){
     9             dfs(v[k][i],k);
    10             sg[k]^=sg[v[k][i]]+1;
    11         }
    12 }
    13 int main(){
    14     scanf("%d",&n);
    15     for(int i=1;i<n;i++){
    16         scanf("%d%d",&x,&y);
    17         v[x].push_back(y);
    18         v[y].push_back(x);
    19     }
    20     dfs(1,0);
    21     if (sg[1])printf("Alice\n");
    22     else printf("Bob\n");
    23     return 0;
    24 }
    View Code
  • 相关阅读:
    C++中变量的作用域与生命周期
    c++运算符优先级归纳
    Debug > CICFlowMeter的java版本安装及使用
    [c3] ::selection选择器
    WIN2016 Server做双网卡绑定
    Linux下配置网卡绑定team
    openfile创建iscsi,并在ESXi里添加
    ESXi下挂载群晖NFS存储
    win10注销linux 子系统 wsl
    linux 中 awk命令统计A、C、T、G碱基数目
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15633264.html
Copyright © 2020-2023  润新知