BZOJ3722: PA2014 Final Budowa

来源:互联网 发布:vb中left是什么意思 编辑:程序博客网 时间:2024/06/05 23:44

资瓷先手为-2,后手为-1,犹豫为0
从叶子开始往上考虑
如果一个人有偶数个0孩子,相当于没有0孩子,可以把他变成-2/-1
如果一个人有奇数个0孩子,且剩余孩子中-2=-1,那么这个人相当于0,否则也可以决定他的决策
一直缩上根,如果根是-2或0则先手必胜否则必败

然后是输出方案
根是-2时显然先手可以任选一个0开始
根是0时,从根往下走,当一个孩子y的状态是0或者y是-1但是y中-2+0的数量=-1的数量,先手就有可能在y中取,往下dfs一遍就好了
O(n)

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<algorithm>#define ll long longusing namespace std;const int maxn = 1100;int n;bool v[maxn];int s[maxn],c[maxn];struct edge{int y,nex;}a[maxn]; int len,fir[maxn];inline void ins(const int x,const int y){a[++len]=(edge){y,fir[x]};fir[x]=len;}void dfs(const int x){    if(c[x]<=0) return;    int v1=0,v2=0,cc=0;    for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)    {        dfs(y);        if(s[y])        {            if(s[y]==-2) v1++;            else v2++;        }        else cc++;    }    cc&=1;    if(!cc)    {        if(v1>v2) s[x]=-2;        else s[x]=-1,v[x]=v2==v1+1?true:false;    }    else    {        if(v1==v2) s[x]=0,v[x]=true;        else s[x]=v1>v2?-2:-1;    }}int t[maxn],tp;void search(const int x){    if(!c[x]) t[++tp]=x;    for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(v[y])        search(y);}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%d",&c[i]);        if(c[i]>0)        {            int m=c[i];            while(m--)            {                int y; scanf("%d",&y);                ins(i,y);            }        }        else s[i]=c[i],v[i]=true;    }    dfs(1);    if(s[1]==-1) puts("NIE");    else    {        if(s[1]==-2)        {            for(int i=1;i<=n;i++) if(!c[i]) t[++tp]=i;        }        else search(1);        sort(t+1,t+tp+1);        printf("TAK %d\n",tp);        for(int i=1;i<=tp;i++)         {            printf("%d",t[i]); if(i!=tp) putchar(' ');        }    }    return 0;}
原创粉丝点击