树形DP的水题。
状态转移方程:
设dp[i][0]为第i号人不去的情况下,以其为根的子树,最大的rating和;dp[i][1]为第i号人去的情况下,以其为根的子树,最大的rating和;
对于树上的每条边:edge[u][ (v[1]) ]……edge[u][ (v[k]) ]……,都有:
dp[u][0]+=∑ max( dp[ (v[k]) ][1] , dp[ (v[k]) ][0] )
dp[u][1]+=∑ dp[ (v[k]) ][0]
将每个人的dp[i][1]按照输入初始化后,用vector记录下一个点的所有孩子,并且找到root,最后进行DFS即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #define MAXN 6005 6 using namespace std; 7 int n,fl[MAXN],dp[MAXN][2],root; 8 vector<int> child[MAXN]; 9 void dfs(int now) 10 { 11 int next; 12 for(int i=0;i<child[now].size();i++) 13 { 14 next=child[now][i]; 15 dfs(next); 16 dp[now][0]+=max(dp[next][1],dp[next][0]); 17 dp[now][1]+=dp[next][0]; 18 } 19 } 20 int main() 21 { 22 memset(fl,0,sizeof(fl)); 23 24 scanf("%d%",&n); 25 26 for(int i=1;i<=n;i++) scanf("%d",&dp[i][1]); 27 for(int i=1;i<=n;i++) 28 { 29 int L,K; 30 scanf("%d%d",&L,&K); 31 child[K].push_back(L); 32 fl[L]=1; 33 } 34 for(int i=1;i<=n;i++) if(fl[i]==0){root=i;break;} 35 36 dfs(root); 37 printf("%d\n",max(dp[root][0],dp[root][1])); 38 }
时间: 2024-11-10 08:15:32