Codeforces 538E Demiurges Play Again(博弈DP)

http://codeforces.com/problemset/problem/538/E

题目大意:

给出一棵树,叶子节点上都有一个值,从1-m。有两个人交替从根选择道路,先手希望到达的叶子节点尽量大,后手希望到达的叶子节点尽量小,叶子节点的放置方案任意。两个人都足够聪明,能够得到的最大值和最小值分别是多少。

思路:

先考虑最大的情况

考虑dp[i]代表i这个节点能达到的最大的数字在这个子树中排第几。

如果当前是先手操作,那么他肯定会往最大的那个子树的方向走,即dp[u]=min(dp[v])

如果当前是后手操作,那么他肯定往最小的走,即dp[u]=Σdp[v],这样就走到了最差子树的最大数字去了。

然后最小的情况类似

 

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 int tot,go[400005],next[400005],first[200005];
 7 int n,f1[400005],f2[400005],pd[400005],son[400005],deep[400005];
 8 int read(){
 9     int t=0,f=1;char ch=getchar();
10     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
11     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
12     return t*f;
13 }
14 void insert(int x,int y){
15     tot++;
16     go[tot]=y;
17     next[tot]=first[x];
18     first[x]=tot;
19 }
20 void add(int x,int y){
21     insert(x,y);
22     insert(y,x);
23 }
24 void dfs(int x,int fa){
25     int pdd=0;
26     for (int i=first[x];i;i=next[i]){
27         int pur=go[i];
28         if (pur==fa) continue;
29         pdd=1;
30         deep[pur]=deep[x]+1;
31         dfs(pur,x);
32         son[x]+=son[pur];
33     }
34     if (!pdd) son[x]=1,pd[x]=1;
35 }
36 void dfs1(int x,int fa){
37     if (pd[x]==1) {
38         f1[x]=1;
39         return;
40     }
41     if (deep[x]%2){
42      f1[x]=0x7fffffff;
43      for (int i=first[x];i;i=next[i]){
44          int pur=go[i];
45          if (pur==fa) continue;
46          dfs1(pur,x);
47          f1[x]=std::min(f1[x],f1[pur]);
48      }
49     }else{
50      f1[x]=0;
51      for (int i=first[x];i;i=next[i]){
52          int pur=go[i];
53          if (pur==fa) continue;
54          dfs1(pur,x);
55          f1[x]+=f1[pur];
56      }
57     }
58 }
59 void dfs2(int x,int fa){
60     if (pd[x]==1) {
61         f2[x]=1;
62         return;
63     }
64     if (deep[x]%2){
65      f2[x]=0;
66      for (int i=first[x];i;i=next[i]){
67          int pur=go[i];
68          if (pur==fa) continue;
69          dfs2(pur,x);
70          f2[x]+=f2[pur];
71      }
72     }else{
73      f2[x]=0x7fffffff;
74      for (int i=first[x];i;i=next[i]){
75          int pur=go[i];
76          if (pur==fa) continue;
77          dfs2(pur,x);
78          f2[x]=std::min(f2[x],f2[pur]);
79      }
80     }
81 }
82 int main(){
83     n=read();
84     for (int i=1;i<n;i++){
85         int x=read(),y=read();
86         add(x,y);
87     }
88     deep[1]=1;
89     dfs(1,0);
90     dfs1(1,0);
91     printf("%d ",son[1]-f1[1]+1);
92     dfs2(1,0);
93     printf("%d
",f2[1]);
94     return 0;
95 }

 

 

 

原文地址:https://www.cnblogs.com/qzqzgfy/p/5627678.html