HDU3094_A Chess Game_树形删边博弈

/*
*State: 3094  156MS    2144K    1315 B    C++
*题目大意:
*        给定n棵树(树中包括简单的多边形),每棵树有m个结点(1~m)和k条边
*        (结点1给根节点)。Harry和Sally轮流删除树上的一条边,并切移除所
*        以和根节点不再连通的所有边和结点。最后不能再删除边的一方为输。
*解题思路:
*        叶子节点的 SG 值为 0;中间节点的 SG 值为它的所有子节点的 SG 值
*        加 1 后的异或和。(加1是因为拆成链的时候,要考虑到链头结点,因为
*        算的其实就是链头的结点。)
*解题感想:
*        略。    
*/
View Code
#include <iostream>
#include <vector>
using namespace std;

const int MAX = 100005;
int sg[MAX], cnt, head[MAX];
bool vst[MAX];
typedef struct node_
{
    int v;
    int next;
}N;
N edge[2 * MAX];

void addEdge(int u, int v)
{
    edge[cnt].v = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;

    edge[cnt].v = u;
    edge[cnt].next = head[v];
    head[v] = cnt++;
}

int dfs(int n)
{
    vst[n] = true;

    if(sg[n] != -1)
        return sg[n];
    if(head[n] == -1)
        return sg[n] = 0;

    vector<int> sg_son;
    for(int f = head[n]; f != -1; f = edge[f].next)
    {
        int son = edge[f].v;
        if(vst[son] == false)
            sg_son.push_back(dfs(son));
    }
    int yihuo = 0;
    for(unsigned i = 0; i < sg_son.size(); i++)
    {
        yihuo ^= sg_son[i] + 1;
    }
    return sg[n] = yihuo;
}

void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(sg, -1, sizeof(sg));
    memset(vst, false, sizeof(vst));
}

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif

    int cas;
    scanf("%d", &cas);
    while(cas--)
    {
        init();
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n - 1; i++)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        int flag = dfs(1);
        if(!flag)
            printf("Bob\n");
        else
            printf("Alice\n");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cchun/p/2614064.html