题目链接:https://www.luogu.com.cn/problem/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
输出格式
输出最大的快乐指数。
输入输出样例
输入 #1
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
输出 #1
5
思路:树形dp入门题
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<stack> #include<map> #include<queue> #include<cmath> using namespace std; typedef long long LL; typedef unsigned long long ull; #define sc1(a) scanf("%lld",&a) #define pf1(a) printf("%lld ",a) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const LL INF=1e18; const ull base=2333; const int maxn=6e3+50; const int maxm=1e2+50; const int maxv=1e6+5; const int mod=1e9+7; const int ba=3e5; LL a[maxn]; vector<LL>v[maxn]; bool is_root[maxn]; LL dp[maxn][5];//dp[i][0]表示职员i不来 dp[i][1]表示职员i来的最大值 void dfs(LL x) { for(int i=0;i<v[x].size();i++) { dfs(v[x][i]); } //儿子全部都算完了 //考虑本身来或者不来 ///如果本身不来的话 当前节点的值等于所以儿子来或者不来的最大值之和 for(int i=0;i<v[x].size();i++) { dp[x][0]+=max(dp[v[x][i]][0],dp[v[x][i]][1]); } ///本身来的话 儿子一定不能来 for(int i=0;i<v[x].size();i++) { dp[x][1]+=dp[v[x][i]][0]; } dp[x][1]+=a[x];//加上本身的值 } int main() { LL N;sc1(N); for(int i=1;i<=N;i++) { sc1(a[i]); } for(int i=1;i<N;i++) { LL L ,K ; sc1(L);sc1(K); v[K].push_back(L);//K是L的直接上司 is_root[L]=true;//L不是根 } LL e1,e2;sc1(e1);sc1(e2); for(int i=1;i<=N;i++)//找到根 { if(!is_root[i]) //找到根l { dfs(i); LL ans=max(dp[i][0],dp[i][1]); pf1(ans); } } return 0; } /** */