Codeforces Round #551 (Div. 2)D(树形DP)

#define HAVE_STRUCT_TIMESPEC
#include <bits/stdc++.h>
using namespace std;
int val[300007],num[300007],ans=0;
vector<int>v[300007];
void dfs(int u){
if(v[u].size()==0){
num[u]=1;
ans++;
return;
}
int tmp=0;
for(int i=0;i<v[u].size();i++){
int vv=v[u][i];
dfs(vv);
tmp+=num[vv];//u所有子树的所有叶子节点个数
if(val[u]==1)
num[u]=min(num[u],num[vv]);//如果是max的话,要使传递到根节点的叶子个数最少,只需要选某颗子树中最少的叶子个数
else
num[u]=max(num[u],tmp);//如果是min的话,别无选择,只能选子树中叶子节点最多的值
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>val[i];
if(val[i]==1)
num[i]=1e9;
else
num[i]=0;
}
for(int i=2;i<=n;i++){
int u;
cin>>u;
v[u].push_back(i);
}
dfs(1);
cout<<ans-num[1]+1;
}

/* 另一种较快的代码,本质思路相同

 

#include<bits/stdc++.h>
using namespace std;
int col[300007];
int dp[300007];
int a[300007];
int head[300007];
int nex[600007];
int to[600007];
int f[300007];
int du[300007];
void dfs(int u,int fa){
if(col[u])
dp[u]=1;
if(a[u]==0){
for(int i=head[u];i;i=nex[i]){
int v=to[i];
if(v==fa)
continue ;
dfs(v,u);
dp[u]+=dp[v];
}
}
else if(!col[u]){
int z=1e9;
for(int i=head[u];i;i=nex[i]){
int v=to[i];
if(v==fa)
continue ;
dfs(v,u);
z=min(z,dp[v]);
}
dp[u]=z;
}
}
int tot;
void add(int u,int v){
nex[++tot]=head[u];//上一条边
head[u]=tot;//最后一条边
to[tot]=v;//连向的点
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int i=2;i<=n;++i){
scanf("%d",&f[i]);
add(f[i],i);
add(i,f[i]);
du[i]++;
du[f[i]]++;
}
int ans=0;
for(int i=2;i<=n;++i){
if(du[i]==1)
col[i]=1,ans++;
}
dfs(1,0);
printf("%d",ans-dp[1]+1);
return 0;
}*/

 

posted @ 2019-08-20 20:38  sewage  阅读(120)  评论(0编辑  收藏  举报