POJ2342 树形dp
原题:http://poj.org/problem?id=2342
树形dp入门题。
我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式:
dp[father][1] += dp[son][0]
dp[father][0] += max(dp[son][0],dp[son][1]);
找到这棵树的根节点,对树向下深搜的过程中进行dp即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 6666; 7 int dp[maxn][2];//dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 8 struct node{ 9 int f;//父节点 10 vector<int>s;//子节点 11 }; 12 node tree[maxn]; 13 int dfs(int cur){ 14 for(int i = 0;i<tree[cur].s.size();i++){ 15 dfs(tree[cur].s[i]); 16 dp[cur][1] += dp[tree[cur].s[i]][0]; 17 dp[cur][0] += max(dp[tree[cur].s[i]][1],dp[tree[cur].s[i]][0]); 18 } 19 } 20 int main(){ 21 int n; 22 while(scanf("%d",&n)!=EOF){ 23 memset(dp,0,sizeof(dp)); 24 for(int i = 1;i<=n;i++) 25 scanf("%d",&dp[i][1]); 26 int l,k; 27 while(scanf("%d%d",&l,&k)&&(l||k)){ 28 tree[l].f = k; 29 tree[k].s.push_back(l); 30 } 31 //寻找根节点 32 int root = 1; 33 while(tree[root].f) 34 root = tree[root].f; 35 dfs(root); 36 printf("%d\n",max(dp[root][0],dp[root][1])); 37 } 38 return 0; 39 }