--------------------
链接:Miku
--------------------
很入门的树形dp,首先,在这个题中,我们要做的就是求出来每一个子节点,然后用他们去更新父亲节点。
对于每一个节点,他有两种状态,去,或者不去,我们定义dp[i][0]为第i个节点也去的状态,而dp[i][1]为它不去,那么很显然
如果这个点去了,它的子节点肯定不去,那么dp[i][1]=dp[孩子们][0]的和,
如果这个点不去,它的子节点可以去也可以不去,那么就是dp[i][0]=max(dp[孩子们][0],dp[sons][1])的和
----------------------
1 #include<iostream> 2 #include<map> 3 #include<cstdio> 4 using namespace std; 5 int n; 6 int r[6001]; 7 int ru[6001]; 8 int x,y; 9 int p; 10 int dp[6001][2]; 11 int head[6001]; 12 struct b{ 13 int t; 14 int ne; 15 } e[6001]; 16 void add(int f,int to){ 17 p++; 18 e[p].t=to; 19 e[p].ne=head[f]; 20 head[f]=p; 21 } 22 int ro; 23 void dfs(int now){ 24 dp[now][0]=0; 25 dp[now][1]=r[now]; 26 for(int i=head[now];i;i=e[i].ne){ 27 dfs(e[i].t); 28 dp[now][0]+=max(dp[e[i].t][1],dp[e[i].t][0]); 29 dp[now][1]+=dp[e[i].t][0]; 30 } 31 } 32 int main(){ 33 cin>>n; 34 for(int i=1;i<=n;++i){ 35 scanf("%d",&r[i]); 36 } 37 for(int i=1;i<=n-1;++i){ 38 scanf("%d%d",&x,&y); 39 add(y,x); 40 ru[x]++; 41 } 42 for(int i=1;i<=n;++i){ 43 // cout<<ru[i]<<" "; 44 if(!ru[i]){ 45 ro=i; 46 break; 47 } 48 } 49 // cout<<ro<<endl; 50 dfs(ro); 51 cout<<max(dp[ro][0],dp[ro][1]); 52 return 0; 53 }