树形dp经典题的稍微变化
题目
Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。
思路:
dp[i][0] 代表i不去,i为根子树的最大欢乐度
dp[i][1] 代表i去,i子树的最大欢乐度
i是叶子:
dp[i][0] = 0;
dp[1][1] = happy[i]
i非叶子:
dp[i][0]=
∑(max(dp[j][0],dp[j][1]))
,j是i的子节点
dp[i][1] = happy[i] +
∑dp[j][0]
#include<iostream>
#include<vector>
#include<cstdio>
#include<memory.h>
#include<algorithm>
using namespace std;
vector< vector<int> > g;
int n;
const int len = 6001;
int dp[len][2];
int happy[len];
void dfs(int i,int src)
{
//is leaf
if(g[i].size() == 1 && g[i][0]== src)
{
dp[i][0] = 0;
dp[i][1] = happy[i];
return;
}
int child;
dp[i][1] = happy[i];
for(size_t k=0; k<g[i].size(); ++k)
{
if(g[i][k]==src)
continue;
child = g[i][k];
dfs( child,i );
dp[i][0] += max(dp[child][1],dp[child][0]);
dp[i][1] += dp[child][0];
}
}
int main()
{
scanf("%d",&n);
g.resize(n);
for(int i=0; i<n; ++i)
scanf("%d",&happy[i]);
if(n==1)
{
cout<<happy[0]<<endl;
return 0;
}
int k,l;
for(int i=0; i<n-1; ++i){
scanf("%d %d",&l,&k);
l--,k--;
g[k].push_back(l);
g[l].push_back(k);
}
scanf("%d %d",&l,&k);
dfs(0,0);
cout<<max(dp[0][0],dp[0][1])<<endl;
}