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\n", ans1, ans2, ans3);
170 }

 

@Author: YouSiki

 

posted @ 2017-02-27 08:13  YouSiki  阅读(578)  评论(4编辑  收藏  举报