大致思路是从根节点DFS下去后,处理完子树信息后,合并然后得出根节点信息,
但是这一题子节点信息的合并确实比较棘手.
如果我们尝试把从当前根节点走K步得到最大苹果数,划分为如下两种:
go[t][i]代表节点t的所有子树上走i步不返回,取得的最大苹果数
bk[t][i]代表节点t的所有子树上走i步并返回,取得的最大苹果数
数组二维go,bk
go[t][i]代表节点t的所有子树上至多走i步不返回,取得的最大苹果数
bk[t][i]代表节点t的所有子树上至多走i步并返回,取得的最大苹果数
求节点为x,实行不断合并子树求最优值
当前合并到了q棵子树:
go[x][i]就是这q棵子树上至多走i步不返回的最优值
bk[x][i]就是这q棵子树上至多走i步并返回的最优值
合并第q+1棵子树(不妨设第q+1棵子树的根为y)的时候,有
go[x][i] = max( bk[x][j]+go[y][i-j], bk[y][j],go[x][i-j] ), j=0.....i
bk[x][i] = max( bk[x][j]+bk[y][i-j] ) j=0,.....i;
关于边界的初始化问题, 对于当前以x为根的树, 因为递归处理好了其子节点J为根的子树,
但是处理子树J的时候,把J节点看作0来处理,回朔到X节点,再处理J节点时再去计算从X走到J的苹果值.
这样,
若计算对于go[j][k] 则需要添加一步由x到j的路径,所以go[j][k] = go[j][k-1]+Apple[j]
若计算对于bk[j][k] 则需要添加来回一趟,共两步从x到j,再回到x的路径,所以bk[j][k] = bk[j][k-2]+Apple[j]
还需要注意, bk[j][1] = bk[j][0] = 0 , go[j][0] = 0, 前者无法走回,后者还没开始走,当然为0
// Code by yefeng1627
// Time 2013-1-17
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<vector>
using namespace std;
const int N = 110;
int go[N][N<<1],bk[N][N<<1],tmp1[N<<1],tmp2[N<<1];
int n, k, Apple[N];
vector<int> Q[N];
int max(int a,int b) {return a>b?a:b;}
void DP(int x, int y )
{
for(int i = 0; i <= k; i++) tmp1[i]=tmp2[i]=0;
for(int i = k; i >= 0; i--)
for(int j = 0; j <= i; j++)
tmp1[i] = max(tmp1[i],max(bk[x][j]+go[y][i-j],go[x][j]+bk[y][i-j]) );
for(int i = k; i >= 0; i--)
for(int j = 0; j <= i; j++)
tmp2[i] = max(tmp2[i],bk[x][j]+bk[y][i-j]);
for(int i = 0; i <= k; i++)
go[x][i] = tmp1[i], bk[x][i] = tmp2[i];
}
void solve(int x, int fa)
{
int y;
for(int i = 0; i < (int)Q[x].size(); i++ )
if( (y=Q[x][i]) != fa )
{
solve( y, x );
for(int L = k; L >= 2; L-- ) bk[y][L] = bk[y][L-2]+Apple[y];
bk[y][1] = bk[y][0] = go[y][0] = 0;
for(int L = k; L >= 1; L-- ) go[y][L] = go[y][L-1]+Apple[y];
DP( x, y );
}
}
int main()
{
while( scanf("%d%d",&n, &k) != EOF )
{
memset(go,0,sizeof(go));
memset(bk,0,sizeof(bk));
for(int i = 0; i < n; i++)
{
scanf("%d", &Apple[i] );
Q[i].clear();
}
int a, b;
for(int i = 0; i < n-1; i++)
{
scanf("%d%d",&a,&b);
a--; b--;
Q[a].push_back(b);
Q[b].push_back(a);
}
solve(0, -1);
printf("%d\n", go[0][k]+Apple[0] );
}
return 0;
}