CF 551 D.Serval and Rooted Tree 树形DP
传送门:http://codeforces.com/contest/1153/problem/D
思路:
这道题想了一天,突发奇想,就是维护每个点两个值,第几大和第几小,就可以有传递性了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define pb push_back typedef long long ll; typedef pair<int, int> pii; const ll inff = 0x3f3f3f3f3f3f3f3f; const int inf = 0x3f3f3f3f; const int maxn = 3e5+9; int a[maxn]; vector<int>mp[maxn]; int dp[maxn][2]; int all = 0; void dfs(int u, int fa) { if(mp[u].size() == 0) dp[u][0] = dp[u][1] = 1, all++; else if(a[u] == 1) dp[u][0] = 0, dp[u][1] = inf; else if(a[u] == 0) dp[u][0] = inf, dp[u][1] = 0; for(int i=0; i<mp[u].size(); i++) { int v = mp[u][i]; if(v == fa) continue; dfs(v, u); if(a[u] == 1) { dp[u][1] = min(dp[v][1], dp[u][1]); dp[u][0] += dp[v][0]; } else { dp[u][1] += dp[v][1]; dp[u][0] = min(dp[v][0], dp[v][1]); } } } 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++) { int x; scanf("%d", &x); mp[x].pb(i); } memset(dp, inf, sizeof(dp)); dfs(1, 1); // cout<<" dp[5][1] = " <<dp[5][1]<<endl; // cout<<dp[1][0] << " , " << dp[1][1]<<endl; printf("%d\n", max(dp[1][0], all - dp[1][1] + 1 )); return 0; }
skr