P1352 没有上司的舞会 - 洛谷
给出一棵 n 个节点的树(职员从属关系),每个节点带权。需要选出一些点,使得它们的权值和最大,并且不存在两个点使得它们是父子关系。
1≤n≤6×103,−128≤ri≤127
这是一个树上的问题,每个节点的选择只会影响到它的父子。
我们随便考虑某一个以 u 为根的子树,假设我们记 dp[u] 表示以 u 为根的子树的最大收益。但是我们会发现这么做无法转移,因为我们不知道 u 这一点有没有被选取。
所以我们需要扩展一维状态记录这个影响转移的关系,而 u 这一点的状态确定之后,它的各个子树也就相互独立了;于是删除或固定当前节点以后,各个儿子子树成为相互独立的子问题,这就可以转化为 DP 求解。
接下来考虑转移:
如果 u 参加,那么它的所有直接下属都不能参加,也就是 dp[u][1]=ru+v∈son(u)∑dp[u][0]。
如果 u 不参加,那么它的直接下属可以参加,也不可以不参加,所以每个儿子 v 我们都选取最优的那个方案:dp[u][0]=v∈son(u)∑max(dp[v][0],dp[v][1])。
vector<int> adj[maxn]; int a[maxn]; ll f[maxn][2]; // 0:不选 | 1:选
voiddfs( int u, int p ){ f[u][1] = a[u]; for( int v : adj[u] ) { if( v == p ) continue; dfs( v, u ); f[u][0] += max( f[v][0], f[v][1] ); f[u][1] += f[v][0]; } }
voidsolve( ){ int n = read( ); for( int i = 1; i <= n; ++ i ) a[i] = read( ); for( int i = 1; i < n; ++ i ) { int u = read( ), v = read( ); adj[u].push_back( v ); adj[v].push_back( u ); }