大意:一棵上下级关系树,直接上司不能和下属一起出席,每人都有权值,求出席party的人价值和最大值。
树形DP:dp[i]// 以i号人为根的关系树,dp [i][1]表示当前树 i 号人出席的价值和最大值,表示当前树 i 号人不出席的价值和最大值。
方程:dp[i][0] +=Σ max(dp[son][0],dp[son][1]);
dp[i][1] +=Σ dp[son][0];
dp[son] 在dp[i]之前算,所以DFS。
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; long long dp[6666][2]; int cnt; int head[6666]; int v[6666]; int in[6666]; struct edge { int to,next; }E[6666]; void addedge(int from , int to) { E[cnt].to = to; E[cnt].next = head[from]; head[from] = cnt++; } void dfs(int now) { for (int i = head[now] ; i != -1 ; i = E[i].next ) { int to = E[i].to; dfs(to); dp[now][0] += max(dp[to][1],dp[to][0]); dp[now][1] += dp[to][0]; } return; } int main() { int N; //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin >> N; memset(dp,0,sizeof(dp)); for (int i = 1; i <= N ; i++) { cin >> dp[i][1]; } int a,b; cnt = 0; memset(head,-1,sizeof head); long long start = N*(N+1)/2; while (cin >> a >> b &&a!=0&&b!=0) { addedge(b,a); start -= (long long)a; } dfs((int)start); cout << max(dp[start][1],dp[start][0]) << endl; }