POJ Anniversary party 树形DP
/* 树形dp: 给一颗树,要求一组节点,节点之间没有父子关系,并且使得所有的节点的权值和最大 对于每一个节点,我们有两种状态 dp[i][0]表示不选择节点i,以节点i为根的子树所能形成的节点集所能获得的最大权值和 dp[i][1]表示选择节点i ,同上! 转移方程: dp[i][0]+=max(dp[i_son][1],dp[i_son][0])如果没选择的话,那么子树可选择可不选择 dp[i][1]+=dp[i_son][0] 选择了之后,子树只能不选择 最后输出max(dp[i][0],dp[i][1])即可 */ #include<iostream> #include<stdio.h> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; #define maxn 6002 vector<int> v[maxn]; bool b[maxn]; int dp[maxn][2],hp[maxn]; void dfs(int k) { int i,len=v[k].size(); dp[k][0]=0 ; dp[k][1]=hp[k]; if(len==0) return ; for(i=0;i<len;i++) { dfs(v[k][i]); dp[k][0]+=max(dp[v[k][i]][1],dp[v[k][i]][0]); dp[k][1]+=dp[v[k][i]][0]; } } int main() { int i,n; int k,l; while(cin>>n) { for(i=1;i<=n;i++) cin>>hp[i],v[i].clear(); memset(b,0,sizeof(b)); while(cin>>l>>k&&k||l) { v[k].push_back(l); b[l]=1; } for(i=1;i<=n;i++) { if(!b[i]) break; } b[i]=1; dfs(i); cout<<max(dp[i][1],dp[i][0])<<endl; } return 0; }