题目描述: 给你一棵树,现在让你选取里面的一些点使得只有偶数个孩子且权值最大,(父节点可以与孙子相连)
分析: 原题版描述的是领导和员工,当时没想到是树结构~~~~~~,现在分析 每个点要保证是偶数点有两种情况 dp[u][0]=dp[u][1]+dp[v][1] u表示父节点,v表示子节点,0表示有偶数个孩子,1表示有奇数个孩子 ,得状态转移方程:
dp[u][1] = max(dp[u][1]+dp[v][0],dp[u][0]+dp[v][1]);
dp[u][0] = max(dp[u][0]+dp[v][0],dp[u][1],dp[u][1]);
为了防止第一个dp[u][1]干扰第二个运算,所以提前设置好变量;
还有一个状态转移方程,看题解理解吧;
注意最后是dp[1][1] 因为还要加上boss的效率是奇数,起始状态都是0个所以效率为0,不可能有奇数个所以设置为负无穷大表示不可能去得到;
最后总结下第一次接触树型dp的理解:
相比一般的这里用的是递归(dfs)进行状态转移,并且枚举的是边,(对应独立两种状态,所以用了两个状态转移方程,可理解为三维dp);
ac代码:
#include<bits/stdc++.h> using namespace std; vector<int> tree[2*100000+4]; long long dp[2*100000+3][2]; int value[2*100000+4]; void dfs(int x){ dp[x][0]=0; dp[x][1]=-200000000005; for(int i=0,sz=tree[x].size();i<sz;i++){ int v=tree[x][i]; dfs(v); long long tmp1=dp[x][1],tmp0=dp[x][0]; dp[x][0]=max(tmp0+dp[v][0],tmp1+dp[v][1]); dp[x][1]=max(tmp1+dp[v][0],tmp0+dp[v][1]); } dp[x][1]=max(dp[x][0]+value[x],dp[x][1]); } int main(){ // freopen("1.txt","r",stdin); int n; cin>>n; for(int i=1;i<=n;i++){ int x; cin>>x>>value[i]; if(i==1)continue; tree[x].push_back(i); } dfs(1); cout<<dp[1][1]<<endl; }