HDU-1520 Anniversary party(树形DP)
题目大意:一棵树,每个节点都带权。从中取出一些节点,并且子节点不能与父节点同时取,求能取得的最大值。
题目分析:定义状态dp(u,0/1)表示u点不取/取。则状态转移方程为:
dp(u,1)=sum(dp(v,0))
dp(u,0)=sum(max(dp(v,1),dp(v,0)))
其中,v为u的子节点。
代码如下:
# include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=1005; int n,w[N*6]; int dp[N*6][2]; bool flag[N*6]; vector<int>e[N*6]; void init() { memset(flag,false,sizeof(flag)); for(int i=1;i<=n;++i){ scanf("%d",w+i); e[i].clear(); } int a,b; while(scanf("%d%d",&a,&b)&&(a+b)) { e[b].push_back(a); flag[a]=true; } } void dfs(int u) { dp[u][1]=w[u]; dp[u][0]=0; for(int i=0;i<e[u].size();++i){ int v=e[u][i]; dfs(v); dp[u][1]+=dp[v][0]; dp[u][0]+=max(dp[v][1],dp[v][0]); } } void solve() { int ans=0; for(int i=1;i<=n;++i){ if(flag[i]) continue; dfs(i); ans+=max(dp[i][1],dp[i][0]); } printf("%d\n",ans); } int main() { while(~scanf("%d",&n)) { init(); solve(); } return 0; }