思路:
树形dp
状态:dp[i][0]表示以i为根节点的子树不选取i的最大贡献
dp[i][1]表示以i为根节点的子树选取i的最大贡献
初始状态:dp[i][0]=0(if i is a leaf)
dp[i][1]=a[i](if i is a leaf)
状态转移:
dp[i][0]=∑max(dp[g[i][j]][0],dp[g[i][j]][1])
dp[i][1]=a[i]+∑dp[g[i][j]][0]
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=6e3+5; vector<int>g[N]; int dp[N][2]; int a[N]; int in[N]; void dfs(int u){ if(g[u].size()==0){ dp[u][0]=0; dp[u][1]=a[u]; return ; } for(int i=0;i<g[u].size();i++){ dfs(g[u][i]); } for(int i=0;i<g[u].size();i++){ dp[u][0]+=max(dp[g[u][i]][1],dp[g[u][i]][0]); dp[u][1]+=dp[g[u][i]][0]; } dp[u][1]+=a[u]; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,u,v; cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; while(cin>>u>>v){ if(u==0&&v==0)break; g[v].pb(u); in[u]++; } int root; for(int i=1;i<=n;i++){ if(in[i]==0){ root=i; break; } } dfs(root); cout<<max(dp[root][0],dp[root][1])<<endl; return 0; }