解题思路:

  • 题目规定不能连续相邻两个房间偷,令dpi,0/1dp_{i,0/1}来表示节点ii为根可以偷到的最大价值,最终结果即max(dp1,0,dp1,1)\max(dp_{1,0},dp_{1,1})
  • 假设ii被偷,则有:dpi,1+=dpis son,0dp_{i,1} += dp_{i's\ son,0}
  • 假设ii没被偷, 则有dpi,0+=max(dpis son,0,dpis son,1)dp_{i,0} += \max(dp_{i's\ son,0},dp_{i's\ son,1})注意ii即使不偷,ii的孩子也可以偷或不偷,而不是一定要偷,取最大值即可。
#include<bits/stdc++.h>
using namespace std;
struct edge{
    int to, next;
}es[200005];
int head[100005], w[100005];
int cnt = 0;
void add_edge(int from, int to){//建图
    es[++cnt].to = to;
    es[cnt].next = head[from];
    head[from] = cnt;
}
int dp[100005][2];
void solve(int i){
    for(int j = head[i]; j; j = es[j].next){
        solve(es[j].to);//先处理son
        dp[i][1] += dp[es[j].to][0];//在偷的情况下,应该是其son不偷的情况下的最大值。
        dp[i][0] += max(dp[es[j].to][0],dp[es[j].to][1]);//在不偷的情况下,应该取son偷或不偷所产生的最大值。
    }
    return;
}
int main(){
    int n;
    int root;
    cin>>n;
    for(int i = 1; i <= n; ++i) cin>>dp[i][1];//初始化dp
    for(int i = 1; i <= n; ++i){
        int fa;
        cin>>fa;
        if(fa == 0) root = i;
        else{
            add_edge(fa, i);
        }
    }
    solve(root);
    cout<<max(dp[root][0], dp[root][1]);
    return 0;
}