hdu 3094 A tree game

http://acm.hdu.edu.cn/showproblem.php?pid=3094

树上删边游戏

一条链的情况:SG分别是0,1,2,……,相当于Nim取石子游戏

那么把边看作石子,树可看做若干堆石子

所以叶节点的SG=0,其余节点的SG等于子节点SG+1的异或和

#include<cstdio>
#include<cstring>

using namespace std;

#define N 100001

int tot,front[N],to[N<<1],nxt[N<<1]; 

int f[N];

void add(int u,int v)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}

void dfs(int u,int fa)
{
    int t;
    for(int i=front[u];i;i=nxt[i])
    {
        t=to[i];
        if(t==fa) continue;
        dfs(t,u);
        f[u]^=(f[t]+1);
    }
}

int main()
{
    int T,n,u,v;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        tot=0;
        memset(front,0,sizeof(front));
        memset(f,0,sizeof(f));
        for(int i=1;i<n;++i)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        dfs(1,0);
        puts(f[1] ? "Alice" : "Bob");
    }
    return 0;
}
         

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12207612.html

时间: 2024-09-06 08:10:28

hdu 3094 A tree game的相关文章

HDU 3094 A tree game 树删边游戏

叶节点SG值至0 非叶节点SG值至于它的所有子节点SG值添加1 XOR和后 #include <cstdio> #include <cstring> #include <vector> using namespace std; vector <int> G[100010]; int sg[100010]; int dfs(int x, int f) { if(sg[x] != -1) return sg[x]; if(!G[x].size()) return

HDU 3094 A tree game 树的删边游戏

叶子节点的SG值为0 非叶子节点的SG值为为它的所有子节点的SG值加1 后的异或和 #include <cstdio> #include <cstring> #include <vector> using namespace std; vector <int> G[100010]; int sg[100010]; int dfs(int x, int f) { if(sg[x] != -1) return sg[x]; if(!G[x].size()) re

hdu 5379 Mahjong tree(树形dp)

题目链接:hdu 5379 Mahjong tree 树形dp,每个节点最多有2个子节点为一棵节点数大于1的子树的根节点,而且要么后代的节点值都大于,要么都小于本身(所以tson不为0是,要乘2).对于K个单一节点的子节点,种类数即为全排K!.当一个节点没有兄弟节点时,以这个节点为根结点的子树,根可以选择最大或者最小. #pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #inclu

HDU 4925 Apple Tree(推理)

HDU 4925 Apple Tree 题目链接 题意:给一个m*n矩阵种树,每个位置可以选择种树或者施肥,如果种上去的位置就不能施肥,如果施肥则能让周围果树产量乘2,问最大收益 思路:推理得到肯定是果树和肥料交叉种好,类似国际象棋棋盘,黑的种,白的施肥,由于格子数不多,直接去枚举每个位置即可.如果题目格子数多的话,其实也可以推出公式一步得到答案 代码: #include <cstdio> #include <cstring> const int d[4][2] = {{0, 1}

HDU 4925 Apple Tree (瞎搞)

找到规律,各一个种一棵树,或者施肥.先施肥,先种树一样. Apple Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 197    Accepted Submission(s): 135 Problem Description I've bought an orchard and decide to plant some

hdu 4925 Apple Tree

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4925 思路:直接计算坐标和,如果为奇数就种树,但要注意行或列为1的情况. 写啦两种代码:一种直接判断计算的,另一种优化计算的 code1: #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> using namespace std; int main() { int T;

HDU 4786 Fibonacci Tree 最小生成树变形

思路: 这题比赛的时候想了好久,最后队友机智的想到了. 不过那时不是我敲的,现在敲的1A. 想好就容易了. 直接把1或者0当做边的权值,然后按边从小到大排序,然后算最小生成用到了几条白边,然后再按边从大到小排序,然后再算白边用了几条.然后最小和最大需要用到的白边都算出来了.如果在这最小最大区间中存在那个啥数列的话就是Yes,否则就是No. 为什么在这区间里面就是对的呢?刚开始我也想了好久,然后发现,因为白边权值是1,然后黑边是0,然后假设用到白边最小的是6,最大的是10,那么,我们可以用黑边去替

HDU 4925 Apple Tree 找呀找规律

间隔着取_(:зゝ∠)_ #include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; int n, m; int init(int i, int j) { int cnt = 1; if(i-1 >= 1) cnt *= 2; if(i+1 <= n) cnt *= 2; if(j-1 >= 1) cnt *=

HDU 3333 Turing Tree 树状数组 离线查询

题意: 给你一个数列,然后有n个查询,问你给定区间中不同数字的和是多少. 思路还是比较难想的,起码对于蒟蒻我来说. 将区间按照先右端点,后左端点从小到大排序之后,对于每个查询,我只要维护每个数字出现的最后一次就可以了(这个结论稍微想一下就可以证明是正确的). 然后就是简单的点更新,区间求和问题了- #include <cstdio> #include <cstring> #include <iostream> #include <map> #include