题目概述
https://www.luogu.com.cn/problem/P1352
思路分析
看到上司的下属之间的关系很容易想到树形结构,那么,又和最值挂钩,那么想到的就是树形dp。那么,这里的可以进行比较的点就是:上司参加,下属就不能参加,下属参加,上司一定不能参加,因此,状态转移的时候我们就需要比较的是上司去和不去的情况,所以,我们把dp数组的第二维开为2:存储上司不去(0)和去(1)时候的最大值。
若上司不去:下属可去可不去,那么,假设下属节点为v,我们要的就是max(dp[v][0],dp[v][1])的和。
若上司去,下属一定不去,那么,我们需要的就是dp[v][0]的和。因为快乐值可能减,所以,在加入上司的时候,还是要比较下val[u]和0的关系,确保值最大。
最后,每一次加完都和ans比较一下,最后输出就可以了
ac代码
#include <iostream>
#include <climits>
using namespace std;
const int maxn=6e3+5;
struct Edge{
int to;
int next;
};
int cnt=0;
int head[maxn];
int w[maxn];
int du[maxn];
Edge e[maxn<<1];
int val[maxn][2]={0};
inline void add(int a,int b){
e[cnt].to=b;
e[cnt].next=head[a];
head[a]=cnt++;
}
int ans=-INT_MAX;
void dfs(int u,int fa){
int t1=0;
int t2=0;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
t1+=max(val[v][0],val[v][1]);
t2+=val[v][0];
}
val[u][0]=t1;
val[u][1]=w[u]+t2;
ans=max(val[u][0],val[u][1]);
}
int main()
{
int n;
cin>>n;
for(int i=0;i<=n;i++) head[i]=-1;
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
du[a]++;
du[b]++;
}
for(int i=1;i<=n;i++){
if(du[i]==1){
dfs(i,-1);
break;
}
}
cout<<ans<<endl;
return 0;
}