HDU 6105 博弈推导

Gameia

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 674    Accepted Submission(s): 267


Problem Description
Alice and Bob are playing a game called 'Gameia ? Gameia !'. The game goes like this :
0. There is a tree with all node unpainted initial.
1. Because Bob is the VIP player, so Bob has K chances to make a small change on the tree any time during the game if he wants, whether before or after Alice's action. These chances can be used together or separate, changes will happen in a flash. each change is defined as cut an edge on the tree. 
2. Then the game starts, Alice and Bob take turns to paint an unpainted node, Alice go first, and then Bob.
3. In Alice's move, she can paint an unpainted node into white color.
4. In Bob's move, he can paint an unpainted node into black color, and what's more, all the other nodes which connects with the node directly will be painted or repainted into black color too, even if they are white color before.
5. When anybody can't make a move, the game stop, with all nodes painted of course. If they can find a node with white color, Alice win the game, otherwise Bob.
Given the tree initial, who will win the game if both players play optimally?
 
Input
The first line of the input gives the number of test cases T; T test cases follow.
Each case begins with one line with two integers N and K : the size of the tree and the max small changes that Bob can make.
The next line gives the information of the tree, nodes are marked from 1 to N, node 1 is the root, so the line contains N-1 numbers, the i-th of them give the farther node of the node i+1.

Limits
T100
1N500
0K500
1Pii
 
Output
For each test case output one line denotes the answer.
If Alice can win, output "Alice" , otherwise "Bob".
 
Sample Input
2 2 1 1 3 1 1 2
 
Sample Output
Bob Alice
 
多校第六场第四道可做题,其实当时我和老胡已经把结论全部推导出来了,但是有一个点没重视,最后没时间了,代码上也没把这个点写出来。
 
题意:有一棵一开始没有颜色的树,Alice和Bob轮流对其染色(Alice先手),Alice每次可以把一个没有颜色的节点染成白色,Bob每次可以把一个没有颜色的节点染成黑色,并且与其直接连接的点无论有颜色与否都会变成黑色,且Bob还可以有一个技能,他能在任何时刻切断两个点之间的连接,共可以切k次。有一个人无法操作,游戏结束,这时树上如果有白色的节点,Alice获胜,否则Bob获胜。
 
这道题起步就是要在草稿上画图,先从两个点开始画,然后加点,加点的过程就像高中增加一个烷基那样,有对称规则,画到后面你就会总结出一些规则
  
   只要满足下面三个任意一个条件Alice就必胜,否则Bob获胜
    
  1.节点为奇数Alice一定会赢
  2.Bob砍枝条的回合与时间无关,可以在能赢一开始就全部砍完,与过程没关系
  3.只要存在一个节点有两个或两个以上的儿子节点是叶子节点,Alice必赢
  4.在3条件(因为3条件下数量上可以砍,但是Bob仍然不会赢,砍不成双双成对的情况)之后Bob的技能使用次数只要能把所有节点分成若干两个一组的点对,就一定能赢。

  我们在想到砍成双双成对的情况的时候,就是判断if(n/2-1>k),已经想到有一种情况是砍不了的,而这种判断没有反映出来,但是没时间了(无奈

 
#include<iostream>
#include <cstdio>
#include<vector>
using namespace std;
vector<int>vt[505];
int ChildSize[505];
int flag=0;
void dfs(int u)
{
    int num=0;//当前(u父亲节点)的儿子是叶子数量,u父亲变化时,num对应的不同层
    ChildSize[u]=1;//包括自己+1
    for(int i=0; i<vt[u].size(); i++)
    {
        int to=vt[u][i];
        dfs(to);
        ChildSize[u]+=ChildSize[to];
        if(ChildSize[to]==1)//如果是儿子是一个叶子节点,则num++
            num++;
    }
    if(num>=2)flag=1;//只要超过两个儿子叶子节点,Alice肯定赢
}
int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=0; i<505; i++)vt[i].clear();
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=2; i<=n; i++)
        {
            int f;
            scanf("%d",&f);
            vt[f].push_back(i);//i的父亲是f
        }
        flag=0;
        dfs(1);
        if(flag==1||n%2==1)printf("Alice
");
        //没有双儿子叶子节点之后在判断可不可以砍成两个一对的
        else if(n/2-1>k)printf("Alice
");
        else printf("Bob
");
    }
}
原文地址:https://www.cnblogs.com/zhangmingzhao/p/7344696.html