hdu6105-多校6&&博弈&图&思维-Gameia

http://acm.hdu.edu.cn/showproblem.php?pid=6105
这道题真的很不错qwq
alice和bob在一个图上玩游戏,bob的技术是,每次到达一个点,就把他邻接的其他点和这个点都染成黑色,而alice则只能染一个色,并且bob是qq会员,可以删除k跳图的边(想啥时候删啥时候删,事实上二人都是老成谋国之人,都是走的最优解,并且也没有同时删除边的数量限制,所以与时间无关。),也就是改变他们的邻接关系啦。问你谁能获胜qwq。
1 如果bob可以把图分为 两个对应的点, 那么他就能染赢。(每个都能完成克制qwq)
而能分成 两个对应的点,要求两种情况
1 一个点不能有大于等于2的 奇数分支。。。(有就分不了。)
)。
2 数量等于偶数。

而 在奇数的点 的情况下,alice每次取 叶子节点的父节点。就能赢。
所以分为以下情况
1 图有 二以上的分叉点, alice赢。
2 图点为 奇数 alice赢。
3 图点为 偶数 且bob可以切割的数量足够 且上图的条件都不成立,bob终于赢了。
4 bob切割力量不够,最后不得不保留一个奇数大小 的子图,被alice血虐,或者自己切割了一个孤立的点。。
这里写图片描述
(两种不能匹配的情况)
这里写图片描述
红色标记 bob想切割的图,如此,则大事尚可为,不然就要别虐。(alice选定叶子节点的父亲。。就这一招。)
这里写图片描述(官方题解,说的更好一点。)



#include <bits/stdc++.h>
using namespace std;
/* alice的策略是,每次都在夜子节点的父节点搞一搞,
这样,bob就会被制衡,必须在这个叶子节点,
而如果有一个节点的siz大于等于2,那么bob小伙子就无法赢。
因为,这样alice染大于2的节点,那么就可以保留一个孤立的点
2 如果没有siz大于2并且节点数目为奇数的,那么就染叶子的节点的父节点,
3 如果siz大于2

dfs1 是错的。2
12 1000
3 4 5 1 2 8 9 4 11 12 4
这个数据。
*/
const int maxn=1e4;
vector<int>G[maxn];
int size[maxn];
int  flag;
void dfs(int u)
{
    int num=0;
    size[u]=1;
    for(int i=0;i<G[u].size();i++)
    {
        int to=G[u][i];
        dfs(to);
        size[u]+=size[to];
        if(size[to]%2==1)num++;
    }
    if(num>=2)flag=1;
}
/*
*/
int dfs1(int m){
    int ans=0;
    for(int i=0;i<G[m].size();i++){
        ans+=dfs1(G[m][i]);
        if(ans>=2) {flag=1;
        //cout<<"!!!!!"<<m<<endl;
        return 0;}//不存在两两配对
    }
    if(G[m].size()==0)
    return 1;
    return 0;
}
int main()
{   freopen("f:\\ttt\\1010.txt","r",stdin);
    freopen("f:\\ttt\\out1.txt","w",stdout);
    int t;
    int m,k,x;
    scanf("%d",&t);
    while(t--){
         memset(size,0,sizeof(size));
         for(int i=0;i<maxn;i++)
             G[i].clear();
         scanf("%d%d",&m,&k);
         for(int i=2;i<=m;i++){
             scanf("%d",&x);
             G[x].push_back(i);
         }
         flag=-1;
         /*for(int i=0;i<=m;i++){
            if(G[i].size()>2)
                flag=true;
         }*/

             dfs(1);
        //if(flag!=-1)
            //cout<<flag<<endl;
            //flag=-1;
         if(m%2==1)
            flag=1;//不存在两两配对
         if(m%2==0){
         if(k>=m/2-1&&flag==-1)
              {  //cout<<"flag"<<flag<<endl;
                  flag=0;}
         else flag=1;
             }
         if(flag==1)
            puts("Alice");
         else if(flag==0)
            puts("Bob");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值