[BZOJ3722]PA2014 Final Budowa

做不来博弈,我真的是太弱了,/(ㄒoㄒ)/

3722: PA2014 Final Budowa

Time Limit: 1 Sec Memory Limit: 128 MB Submit: 421 Solved: 147 [Submit][Status][Discuss]

Description

Fancy爷宣布XJOI群将要选举下一任群主。候选人有两名,分别是XYW和吉丽。 共有n个人(从1~n编号)参加这次投票。他们之间形成了一个树结构,根结点(1号结点)为Fancy。树上的结点有两种身份:专家(叶子结点)或领导(非叶子结点)。每位专家都有自己的选择——支持XYW和吉丽之中的一个;每位领导都有若干个下属(儿子结点),领导的选择决定于下属中人数较多的那一方,下属的数目保证为奇数,从而不会出现平局状况。最后,Fancy的选择即为选举结果。 吉丽和XYW知道,目前仍有一些专家处于犹豫未决的状态,只要前去游说,就可获得他的支持。但是由于精力不够,每人每天只能选择游说1名专家;XYW起床更早,他比吉丽先进行游说。这样两人交替进行,直到每位专家都有了确定的选择。请问XYW是否有策略保证自己赢得选举胜利?

Input

第一行一个整数n(2<=n<=1000),表示人数。 接下来有n行。第i行中,第一个数为ci。如果c[i]<=0,则i是专家,-2表示其支持XYW,-1表示支持吉丽,0表示仍在犹豫;如果c[i]>0,则c[i]为奇数,表示i是领导,其后c[i]个整数为i的下属。 (数据保证为树结构,即除了根节点1以外每个结点有且仅有一个上级)

Output

若XYW无法保证胜利,仅输出一行NIE。 否则,输出第一行包含TAK和一个非负整数d;输出第二行包含d个整数,按升序排列,表示XYW在必胜策略下,第一天可以选择游说的专家的编号。(如果不存在犹豫不决的专家,且XYW获得胜利的情况下,则d=0,第二行为空行)

Sample Input

4 3 2 3 4 -2 0 -1

Sample Output

TAK 1 3

HINT

Source

考虑对于某一个上司,他若有偶数个0下属其实就等同于他没有0下属,即最后0下属个数%2.如果有0下属,-1和-2相同,那么这个上司看做一个0的专家状态.否则我们看下-1和-2哪个多,就必定是最后这个上司的状态. dfs判定完之后如果1号点的状态-1就nie,否则tak.对于选择,直接暴力枚举(对没错,n才1000暴枚啊),每个0下属最开始选,暴力dfs重判一下1号点是否是-2就可以了.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;
const int maxn = 4e3+5;
int en[maxn],nt[maxn],la[maxn],owo;
void adg(int x,int y) {
    en[++owo] = y; nt[owo] = la[x]; la[x] = owo; 
}
int n;
int SX[maxn],ZT[maxn];
int sta[maxn],top;
bool flag = 0;
void DFS(int x) {
    if(!la[x]) {
        ZT[x] = SX[x];
        if(flag) return;
        if(ZT[x]==0) sta[++top] = x;
        return;
    }
    int li = 0 , yi = 0 , er = 0;
    for(int it=la[x];it;it=nt[it]) {
        int y = en[it];
        DFS(y);
        if(ZT[y]==-1) yi++;
        else if(ZT[y]==-2) er++;
        else li++;
    }
    li&=1;
    if(!li) {
        if(yi>er) ZT[x] = -1;
        else ZT[x] = -2;
    } else {
        if(yi==er) ZT[x] = 0;
        else if(yi>er) ZT[x] = -1;
        else ZT[x] = -2;
    }
    return;
}
int OO;
int woc[maxn],wc;
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d",&SX[i]);
        if(SX[i]>0) {
            for(int j=1;j<=SX[i];j++) {
                int x; scanf("%d",&x);
                adg(i,x);
            }
        }
    }
    DFS(1);
    flag = 1;
    if(ZT[1]==-1) { printf("NIE"); return 0;}
    for(int i=1;i<=top;i++) {
        SX[sta[i]] = -2; DFS(1); SX[sta[i]] = 0;
        if(ZT[1]==-2) woc[++wc] = sta[i];
    }
    sort(woc+1,woc+1+wc);
    printf("TAK %d\n",wc);
    for(int i=1;i<=wc;i++) printf("%d ",woc[i]);
}
posted @ 2019-01-21 17:08  Newuser233  阅读(6)  评论(0编辑  收藏  举报