题目大意:一棵树,每个节点都带权。从中取出一些节点,并且子节点不能与父节点同时取,求能取得的最大值。
题目分析:定义状态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;
}