p1352 没有上司的舞会
题目
某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
输入格式:
第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0 0
输出格式:
输出最大的快乐指数。
分析
一道经典的树型dp模板题,dp[i][0/1]表示第i个节点选还是不选,因为如果一个点选了它的儿子都不能选,一个点如果不选它的儿子既可以选也可以不选,所以我们不难得出代码中的转移方程
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
int n,m;
vector<int>v[6010];
int dp[6500][3];
int val[6500];
void dfs(int x,int fa){
int i;
dp[x][1]=val[x];
if(v[x].size()==0)return;
for(i=0;i<v[x].size();i++)
if(v[x][i]!=fa){
dfs(v[x][i],x);
dp[x][0]+=max(0,max(dp[v[x][i]][0],dp[v[x][i]][1]));
dp[x][1]+=max(0,dp[v[x][0]][0]);
}
return;
}
int main(){
int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
cin>>val[i];
for(i=1;i<n;i++){
int x,y;
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
cin>>i>>j;
dfs(1,0);
cout<<max(dp[1][0],dp[1][1])<<endl;
return 0;
}