没有上司的舞会
考点: 树形 d p dp dp
思路:
d
p
[
u
]
[
0
]
dp[u][0]
dp[u][0]表示第u
个结点不去产生的最大价值,
d
p
[
u
]
[
1
]
dp[u][1]
dp[u][1]表示第u
个结点去产生的最大价值,状态转移方程为,设j
为u
的儿子结点:
{ d p [ u ] [ 0 ] = d p [ u ] [ 0 ] + ∑ m a x ( d p [ j ] [ 1 ] , d p [ j ] [ 0 ] ) d p [ u ] [ 1 ] = d p [ u ] [ 1 ] + ∑ d p [ j ] [ 0 ] + w [ u ] \begin{cases} dp[u][0] = dp[u][0] + \sum{max(dp[j][1], dp[j][0])}\\ \\ dp[u][1] = dp[u][1] + \sum{dp[j][0]} + w[u]\end{cases} ⎩⎪⎨⎪⎧dp[u][0]=dp[u][0]+∑max(dp[j][1],dp[j][0])dp[u][1]=dp[u][1]+∑dp[j][0]+w[u]
从根结点 d f s dfs dfs一遍即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int h[N], ne[N], e[N], idx;
int w[N];
LL dp[N][2];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
LL dfs(int u){
dp[u][1] = w[u];
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
dfs(j);
dp[u][0] = dp[u][0] + max(dp[j][1], dp[j][0]);
dp[u][1] = dp[u][1] + dp[j][0];
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
cin >> n;
memset(h, -1, sizeof h);
for(int i = 2; i <= n; i ++ ){
int x;
cin >> x;
add(x, i);
}
for(int i = 1; i <= n; i ++ ){
cin >> w[i];
}
dfs(1);
LL ans = -1;
for(int i = 1; i <= n; i ++ ){
ans = max({ans, dp[i][1], dp[i][0]});
}
cout << ans;
}