HDU1520 Anniversary party(树形dp入门题)
题意:
给定一棵关系树,每个节点有个权值,子节点和父节点不能同时选,问最后能选的最大价值是多少?
思路:
dp[i][1]表示选,dp[i][0]表示不选
则状态转移方程为:
dp[i][1]+=dp[j][0];
dp[i][0]+=max(dp[j][1],dp[j][0]);
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <cmath> #include <algorithm> using namespace std; #define N 6010 int dp[N][2]; vector<int>son[N]; bool vis[N]; void treedp(int p) { vis[p]=1; for(int i=0; i<son[p].size(); i++) { int u=son[p][i]; if(!vis[u]) treedp(u); dp[p][1]=dp[p][1]+dp[u][0]; dp[p][0]=dp[p][0]+max(dp[u][0],dp[u][1]); } } int main() { //freopen("in.txt","r",stdin); int n,p,q; while(~scanf("%d",&n)) { memset(dp,0,sizeof(dp)); for(int i=1; i<=n; i++) { scanf("%d",&dp[i][1]); son[i].clear(); } memset(vis,0,sizeof(vis)); while(scanf("%d%d",&p,&q)&&(p+q)) { son[q].push_back(p); vis[p]=1; } int root; for(int i=1; i<=n; i++) if(!vis[i]) { root=i; break; } memset(vis,0,sizeof(vis)); treedp(root); printf("%d\n",max(dp[root][0],dp[root][1])); } return 0; }