题解:
树形dp
首先开始做时我以为只要贪心选取就可以了...
后来发现根节点可以不用选,而选和为奇数的满足条件的子节点.
所以需要重新构建状态
dp[u][0]表示满足条件的以u为根节点的子树中,节点数为偶数的最大值
dp[u][0]表示满足条件的以u为根节点的子树中,节点数为奇数的最大值
最开始不选根节点.dp[u][0]=0,dp[u][1]为-INF(不存在)
每次加子节点v时
1.偶可以由偶(u)+偶(v),奇(u)+奇(v)更新
2.奇可以由奇(u)+奇(v),奇(u)+奇(v)更新
最后当子节点条件完后,所有子节点的和为偶的情况可以加上根节点
dp[u][1]=max(dp[u][1],dp[u][0]+1);
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=200005; const int mod=1000000007; int n,x; int w[maxn]; ll dp[maxn][2]; vector<int> s[maxn]; void dfs(int u) { dp[u][0]=0;dp[u][1]=-(1LL<<60); for(int i=0;i<s[u].size();i++) { int v=s[u][i]; dfs(v); ll t0=dp[u][0],t1=dp[u][1]; t0=max(t0,dp[u][0]+dp[v][0]); t0=max(t0,dp[u][1]+dp[v][1]); t1=max(t1,dp[u][1]+dp[v][0]); t1=max(t1,dp[u][0]+dp[v][1]); dp[u][0]=t0; dp[u][1]=t1; } dp[u][1]=max(dp[u][1],dp[u][0]+w[u]); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&w[i]); if(x==-1) continue; s[x].push_back(i); } dfs(1); printf("%lld\n",max(dp[1][0],dp[1][1])); return 0; }
时间: 2024-11-03 01:25:11