cf上一个树dp的题目

代码留存,
状态设计的一种方法
没做过这种题真的感觉有点厉害

题目地址
题解地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define inc(i,a,b) for(int i=a;i<=b;i++)
#define pb push_back

const int maxv=3e5+5;
vector<int> G[maxv];

//在以i为根的子树上,dp[i]表示最大的数
//是在以i为根的子树上的的第i小的数

int dp[maxv],a[maxv];
bool vis[maxv];

int cnt;
void (int u){
if(G[u].size()==0){
dp[u]=1;
return;
}
if(a[u]) dp[u]=inf;
else dp[u]=0;

for(int i=0;i<G[u].size();i++){
dfs(G[u][i]);
if(a[u]) dp[u]=min(dp[u],dp[G[u][i]]);
else dp[u]+=dp[G[u][i]];
}
}


int n;
int main(){
scanf("%d",&n);
inc(i,1,n) scanf("%d",a+i);
inc(i,2,n) {
int u;scanf("%d",&u);
G[u].pb(i);
vis[u]=1;
}
inc(i,1,n) if(!vis[i]) cnt++;
dfs(1);
printf("%dn",cnt+1-dp[1]);
}

要加油啊
新的生活马上就要开始了