一千八的题也不会做了呜呜呜
size[u]表示结点u下的叶子结点,
思维:可以想到一个子树对其父亲会有一个消耗值
考虑一个点如果是max,那么其最大值可以是size[u]-p,p是消耗值最小的子树
一个点如果是min,那么其最大值是size[u]-所有子树的消耗值之和
那么dp[u]表示结点u的最大值为size[u]-dp[u]+1
dp[u]表示结点u的消耗值
叶子结点的消耗值为1,
max结点的消耗值为消耗值最小的子树
dp[u]=min(dp[v])
那么这个结点的结果是size[u]-dp[u]+1
min结点的消耗值为子树的消耗值之和dp[u]=sum(dp[v])
最后的答案是size[1]-dp[1]+1
#include<bits/stdc++.h> using namespace std; #define maxn 300005 struct Edge{int to,nxt;}edge[maxn<<1]; int flag[maxn],a[maxn],head[maxn],tot,n; void addedge(int u,int v){ edge[tot].to=v;edge[tot].nxt=head[u];head[u]=tot++; } void init(){ tot=0; memset(head,-1,sizeof head); } int size[maxn]; void getsize(int u,int fa){ if(flag[u]==0){size[u]=1;return;} for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==fa)continue; getsize(v,u); size[u]+=size[v]; } } int dp[maxn]; void dfs(int u,int fa){ if(flag[u]==0){dp[u]=1;return;} int sum=0,Min=0x3f3f3f3f; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==fa)continue; dfs(v,u); sum+=dp[v]; Min=min(Min,dp[v]); } if(a[u])dp[u]=Min; else dp[u]=sum; } int main(){ init(); cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int u=2;u<=n;u++){ int fa; cin>>fa; flag[fa]=1; addedge(u,fa); addedge(fa,u); } getsize(1,0); dfs(1,0); cout<<size[1]-dp[1]+1<<endl; }