HDU 6105 Gameia

来源:互联网 发布:中国近代史知乎 编辑:程序博客网 时间:2024/06/04 18:43

题目地址
题意:给你一个树,然后对节点进行染色,告诉你有n个节点,以及Bob有m次删边的机会,你随时随地都可以删(其实这就是一个屁话,和一开始删除是一样的),然后n-1个数,告诉你从2到n的父亲节点是哪个点,给点染色的方法是

Alice可以任选一个空节点染色(白色)
Bob选择一个空节点染色(黑色),然后把他的儿子节点也给染色(不管之前是什么颜色,之后都为黑色)

思路:就是一个图+博弈的题目,其实很好理解,因为Bob想赢就会尽可能得把Alice的覆盖掉去,如果点数为奇数的话,最后是Alice连,所以Alice一定是赢的,然后就是把图分为两两匹配的,如果想要构成两两匹配的删边数不大于m并且不会有两个及以上的没有子节点的子节点的话就是Bob赢了(PS:因为有大于等于两个的子节点没有子节点的话就会有单独的点不能用Bob的技能覆盖掉去了,那样的话Alice就赢了)

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#define N 510#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;int n, m;vector<int> v[N];bool vis[N];void init() {    for (int i = 0; i <= n; i++) {        v[i].clear();    }    memset(vis, false, sizeof(vis));}int main() {    cin.sync_with_stdio(false);    int T;    int a;    bool flag;    cin >> T;    while (T--) {        cin >> n >> m;        init();        flag = true;        for (int i = 2; i <= n; i++) {            cin >> a;            v[a].push_back(i);            vis[a] = true;//为该节点的父亲进行标记        }        for (int i = 1; i <= n; i++) {            int sum = 0;            for (int j = 0; j < v[i].size(); j++) {                if (!vis[v[i][j]]) {//以他为根节点周围有几个子节点没有他的子节点                    sum++;                }            }            if (sum > 1) {                flag = false;                break;            }        }        if (m >= (n / 2 - 1) && flag&&n % 2 == 0) {            cout << "Bob" << endl;        }        else {            cout << "Alice" << endl;        }    }    return 0;}
原创粉丝点击