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

来源:互联网 发布:mac电磁阀说明书 编辑:程序博客网 时间:2024/05/18 20:12

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大于2dfs1 是错的。212 10003 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;}
原创粉丝点击