zoukankan      html  css  js  c++  java
  • BZOJ 3164: [Heoi2013]Eden的博弈问题

    3164: [Heoi2013]Eden的博弈问题

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 134  Solved: 98
    [Submit][Status][Discuss]

    Description


    对于有两个玩家的,状态透明且状态转移确定的博弈游戏,博弈树是常用的分析工具。博弈树是一棵有根树,其中的节点为游戏的状态。若节点B的父亲是A,则说明状态A能通过一次决策转移到状态B。每个状态都有一个唯一的决策方,即这个状态下应该由哪一方做出决策。我们规定双方在任何时候都是轮流做出决策的,即树上相邻节点的决策方总是不相同的。在这个问题中,我们只关心两个玩家的胜负情况,且规定游戏不会出现平局。 我们称两个玩家分别为黑方和白方,其中根节点的决策方为黑方。显然每个节点 只有两个状态:黑方胜和白方胜。若某内节点(即存在后继节点的节点)的决策 方为黑方,则该节点为黑方胜的充要条件为它的儿子中存在黑方胜的节点,反之亦然。求解博弈树即为判明博弈树根节点的状态。如果我们得知了所有叶节点(即无后继节点的节点)的状态,那么博弈树就 很容易求解了。但是现在的情况是所有叶节点的状态均为未知的,需要进一步的计算。对于一个由叶节点构成的集合S,如果S中的节点均被判明为黑方胜,就可以断言根节点为黑方胜的话,则称 S为一个黑方胜集合。对于黑方胜集合 S,
    如果对于任意的黑方胜集合 S’均满足|S| ≤ |S’ |(|S|表示集合S中的元素数目),
     则称S为一个最小黑方胜集合。同样地,也可以定义白方胜集合和最小白方胜集合。 
     Eden最近在研究博弈树问题。他发现,如果一个叶节点既属于某一个最小黑方胜集合,又属于一个最小白方胜集合,那么求解这个节点的状态显然最有益 于求解根节点的状态。像这样的叶节点就称之为关键叶节点。对于一棵给定的博弈树,Eden想要知道哪些叶节点是关键叶节点。 

    Input

     
    每个测试点包含一组测试数据。 
    测试数据的第一行包含一个正整数n,表示博弈树的节点数目。节点从1到n 编号,且 1 号节点为根节点。 
    之后n–1 行,每行包含一个正整数。第i行的正整数表示节点i的父节点的编号。 

    Output

    在一行内输出三个空格分隔的正整数,分别是编号最小的关键叶节点的编号,
    关键叶节点的数目和所有关键叶节点的编号的异或和。 

    Sample Input

    7
    1
    1
    2
    2
    3
    3


    Sample Output


    4 4 0

    HINT

    对于100% 的数据,1 ≤  n ≤ 200,000 ,且对于节点 i(i ≠ 1 ),其父节点的编号小于i。 

     

    Source

     
    [Submit][Status][Discuss]

    这贪心好水啊~~~

      1 #include <cstdio>
      2 
      3 template <class T>
      4 inline T min(const T &a, const T &b)
      5 {
      6     return a < b ? a : b;
      7 }
      8 
      9 const int mxn = 200005;
     10 const int inf = 1000000007;
     11 
     12 int n, fat[mxn];
     13 
     14 int hd[mxn];
     15 int to[mxn];
     16 int nt[mxn];
     17 
     18 inline void addEdge(int u, int v)
     19 {
     20     static int tot = 0;
     21     nt[++tot] = hd[u];
     22     to[tot] = v;
     23     hd[u] = tot;
     24 }
     25 
     26 int dep[mxn];
     27 
     28 void preDFS(int u, int d)
     29 {
     30     dep[u] = d;
     31     
     32     for (int i = hd[u]; i; i = nt[i])
     33         preDFS(to[i], d ^ 1);
     34 }
     35 
     36 namespace tree1
     37 {
     38     int f[mxn];
     39     int v[mxn];
     40     
     41     void DFS1(int u)
     42     {
     43         if (!hd[u])
     44             f[u] = 1;
     45         else
     46         {
     47             if (dep[u])
     48             {
     49                 f[u] = 0;
     50                 
     51                 for (int i = hd[u]; i; i = nt[i])
     52                     DFS1(to[i]), f[u] = f[u] + f[to[i]];
     53             }
     54             else
     55             {
     56                 f[u] = inf;
     57                 
     58                 for (int i = hd[u]; i; i = nt[i])
     59                     DFS1(to[i]), f[u] = min(f[u], f[to[i]]);
     60             }
     61         }
     62     }
     63     
     64     void DFS2(int u)
     65     {
     66         if (!hd[u])
     67             v[u] = 1;
     68         else
     69         {
     70             if (dep[u])
     71             {
     72                 for (int i = hd[u]; i; i = nt[i])
     73                     DFS2(to[i]);
     74             }
     75             else
     76             {
     77                 for (int i = hd[u]; i; i = nt[i])
     78                     if (f[to[i]] == f[u])DFS2(to[i]);
     79             }
     80         }
     81     }
     82     
     83     inline void solve(void)
     84     {
     85         DFS1(1);
     86         DFS2(1);
     87     }
     88 }
     89 
     90 namespace tree2
     91 {
     92     int f[mxn];
     93     int v[mxn];
     94     
     95     void DFS1(int u)
     96     {
     97         if (!hd[u])
     98             f[u] = 1;
     99         else
    100         {
    101             if (!dep[u])
    102             {
    103                 f[u] = 0;
    104                 
    105                 for (int i = hd[u]; i; i = nt[i])
    106                     DFS1(to[i]), f[u] = f[u] + f[to[i]];
    107             }
    108             else
    109             {
    110                 f[u] = inf;
    111                 
    112                 for (int i = hd[u]; i; i = nt[i])
    113                     DFS1(to[i]), f[u] = min(f[u], f[to[i]]);
    114             }
    115         }
    116     }
    117     
    118     void DFS2(int u)
    119     {
    120         if (!hd[u])
    121             v[u] = 1;
    122         else
    123         {
    124             if (!dep[u])
    125             {
    126                 for (int i = hd[u]; i; i = nt[i])
    127                     DFS2(to[i]);
    128             }
    129             else
    130             {
    131                 for (int i = hd[u]; i; i = nt[i])
    132                     if (f[to[i]] == f[u])DFS2(to[i]);
    133             }
    134         }
    135     }
    136     
    137     inline void solve(void)
    138     {
    139         DFS1(1);
    140         DFS2(1);
    141     }
    142 }
    143 
    144 signed main(void)
    145 {
    146     scanf("%d", &n);
    147     
    148     for (int i = 2; i <= n; ++i)
    149         scanf("%d", fat + i);
    150     
    151     for (int i = 2; i <= n; ++i)
    152         addEdge(fat[i], i);
    153     
    154     preDFS(1, 0);
    155     
    156     tree1::solve();
    157     tree2::solve();
    158     
    159     int ans1 = inf, ans2 = 0, ans3 = 0;
    160     
    161     for (int i = 1; i <= n; ++i)
    162         if (tree1::v[i] && tree2::v[i])
    163         {
    164             ans1 = min(ans1, i);
    165             ans2 = ans2 + 1;
    166             ans3 = ans3 ^ i;
    167         }
    168     
    169     printf("%d %d %d
    ", ans1, ans2, ans3);
    170 }

    @Author: YouSiki

  • 相关阅读:
    写个三个月后的我
    设置gridcontrol的焦点行
    希望我能更快的成长
    女人最想要的是什么
    初始化时查看combox的文本内容
    获取一个gridcontrol的数据行数
    第八章:Applet基础学习
    浅谈研发项目经理的技能要求
    学习C和C++应该看的书
    双缓冲绘图
  • 原文地址:https://www.cnblogs.com/yousiki/p/6471838.html
Copyright © 2011-2022 走看看