ICPC Southeastern Europe Contest 2019 D Game on a Tree

Game on a Tree
Alice and Bob play a game on a tree. Initially, all nodes are white.

Alice is the first to move. She chooses any node and put a chip on it. The node becomes black. After that players take turns. In each turn, a player moves the chip from the current position to an ancestor or descendant node, as long as the node is not black. This node also becomes black. The player who cannot move the chip looses.

Who wins the game?

An ancestor of a node v in a rooted tree is any node on the path between v and the root of the tree.

A descendant of a node v in a rooted tree is any node w such that node v is located on the path between w and the root of the tree.

We consider that the root of the tree is 1.

Input

The first line contains one integer n (1≤n≤100000)n(1≤n≤100000) — the number of nodes.Each of the next n−1n−1 lines contains two integers uu and vv (1≤u,v≤n)(1≤u,vn) — the edges of the tree. It is guaranteed that they form a tree.

Output

In a single line, print “Alice” (without quotes), if Alice wins. Otherwise, print “Bob”.

输出时每行末尾的多余空格,不影响答案正确性

样例输入1
4
1 2
2 3
3 4
样例输出1
Bob
样例输入2
7
2 1
2 6
1 3
2 5
7 2
2 4
样例输出2
Alice

解题思路:

由题目可以知道,该游戏为一人走一步,并且只能在当前位置进行移动,那么我们可以考虑将每两个点进行匹配;

我们可以考虑,假设有n个点,那么这几个点分为n / 2组,两两进行匹配的话可以得到集合**{(p1 , p2) , (p3 , p4) , …(pn-1, pn+1)}**;

第一种情况:

如果所有的点都进行了匹配,即完美匹配,我们可以推出,先手每走一步,后手就只能走与之相匹配的点上,则最大匹配完美匹配的情况下,后手必赢,即B必赢;

第二种情况:

该图的最大匹配如果不是完美匹配,即还有点无法进行匹配(点之间无连线),那么如果先手选择一个不在匹配内的点时,可以推得先手必赢,即A必赢;

考虑到这里后,只需要解决该图的最大匹配数是否为完美匹配就可以解决这道题目;使用dfs则可以找到该图的完美匹配数;

这里我们设置一个数组s[ ] 来进行dfs,s[ i ]表示以 i 为根节点的子树所剩下的未匹配的节点的个数,那么我们只要从叶子节点进行贪心,往上匹配即可;

AC代码:

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#include<stack>
#include<queue>
#include<sstream>
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;
const int mod = 1e9 + 7;
const ll maxn = 100005;
const double pi = acos(-1.0);

int n;
vector<int> edge[maxn];
int s[maxn]; // 以i为根的子树,最大匹配后剩下的点的个数

void dfs(int x, int root)
{
    for(auto i : edge[x])   //遍历图
    {
        if(i == root)
            continue;
        dfs(i,x);
        s[x] += s[i];
    }
    if(s[x] != 0)
        s[x] -= 1;
    else
        s[x] = 1;
}

int main()
{
    while(cin >> n)
    {
        for(int i = 1; i < n; i ++)
        {
            int u,v;
            cin >> u >> v;
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        dfs(1,0);
        if(s[1] == 0)
            cout << "Bob" << endl;
        else
            cout << "Alice" << endl;
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值