POJ 2486-Apple Tree(树状背包)
题意
n个节点的树,每个节点都有价值,求在树上最多走k步获得的最大价值(从1开始走,节点的价值只能获取一次)
分析:
开始以为是最基础的树形背包,但后来发现,不能只走子树,有可能还回到根节点,dp[i][j][0]走子树后用回到根,dp[i][j][1],不用回到根
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; struct tree{ int u,v,next,val; }t[510]; int dp[210][410][2],head[210],v[210],used[210]; int n,len,k; void add(int a,int b){ t[len].u=a; t[len].v=b; t[len].next=head[a]; head[a]=len++; } void dfs(int root){ used[root]=1; for(int i=head[root];i!=-1;i=t[i].next){ int son=t[i].v; if(used[son])continue; dfs(son); for(int j=k;j>=1;--j) for(int l=1;l<=j;++l) { dp[root][j][0]=max(dp[root][j][0],dp[root][j-l][0]+dp[son][l-2][0]);//回根步数减2,不回根步数减1 dp[root][j][1]=max(dp[root][j][1],dp[root][j-l][1]+dp[son][l-2][0]); dp[root][j][1]=max(dp[root][j][1],dp[root][j-l][0]+dp[son][l-1][1]); } } } int main() { while(~scanf("%d%d",&n,&k)){ memset(dp,0,sizeof(dp)); memset(head,-1,sizeof(head)); memset(used,0,sizeof(used)); for(int i=1;i<=n;++i) { scanf("%d",&v[i]); for(int j=0;j<=k;++j) dp[i][j][0]=dp[i][j][1]=v[i]; } int a,b; len=0; for(int i=0;i<n-1;++i){ scanf("%d%d",&a,&b); add(a,b); add(b,a); } dfs(1); printf("%d\n",max(dp[1][k][0],dp[1][k][1])); } return 0; }