解题思路
一道树形DP的模板,设f[i][0,1]表示第i个节点的子树的最大值和,0/1表示选或不选这个节点,设y表示x的儿子,得:
- f [ x ] [ 0 ] = m a x ( f [ y ] [ 0 ] , f [ y ] [ 1 ] ) f[x][0]=max(f[y][0],f[y][1]) f[x][0]=max(f[y][0],f[y][1])
- f [ x ] [ 1 ] = f [ y ] [ 0 ] + r x f[x][1]=f[y][0]+r_x f[x][1]=f[y][0]+rx
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
using namespace std;
int n,x,y,k,head[6100],f[6100][2],r[6100],v[6100];
struct c{
int x,next;
}a[6100];
void add(int x,int y)
{
a[++k].x=y;
a[k].next=head[x];
head[x]=k;
}
void dfs(int dep){
f[dep][1]=r[dep];
for(int i=head[dep];i;i=a[i].next)
{
int y=a[i].x;
dfs(y);
f[dep][0]+=max(f[y][1],f[y][0]);
f[dep][1]+=f[y][0];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&r[i]);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
add(y,x);
v[x]++;
}
for(int i=1;i<=n;i++)
{
if(!v[i])
{
dfs(i);
printf("%d",max(f[i][0],f[i][1]));
return 0;
}
}
}