洛谷-P1352 没有上司的舞会
题意:
某大学有1-n个职员
他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。
现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 ,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。
所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。
链接:https://www.luogu.com.cn/problem/P1352
输入:
输入的第一行是一个整数 n。
第二行到第n+1行,每行一个数代表快乐值接下来n行每行两个数x,y,代表y是x的上司
输出:
最大的快乐值
思路:
树形DP,设dp[i][0]代表这个职工去了,dp[i][1]代表这个职工没去,v代表该职工的手下
如果该职工去了那么他的手下就不能再去,所以得到转移方程dp[i][0]=dp[i][0]+dp[v][1]
如果该职工没去他们他的手下就可以去,所以要考虑他的手下去或不去的两种情况,
所以得到dp[i][1]=dp[i][1]+max(dp[v][0],dp[v][1]);
在回溯的时候由叶子节点向根节点更新
代码:
#include <bits/stdc++.h> using namespace std; const int MAXN = 2e5+ 5; const int INF = 1e16; typedef long long ll; int a[MAXN],dp[7000][2],fa[MAXN]; vector<int>v[MAXN]; void dfs(int u) { for(int i=0; i<v[u].size(); i++) { int nxt=v[u][i]; dfs(nxt); dp[u][0]+=dp[nxt][1]; dp[u][1]+=max(dp[nxt][0],dp[nxt][1]); } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; for(int i=1; i<=n; i++) { cin>>dp[i][0]; } for(int i=1;i<=n-1;i++) { int x,y; cin>>x>>y; if((!x)&&(!y)) break; v[y].push_back(x); fa[x]=1; } int index=0; for(int i=1; i<=n; i++) { if(!fa[i]) { index=i; break; } } dfs(index); cout<<max(dp[index][0],dp[index][1]); }