^_^ o(∩∩)o...我去刚要打个哈哈出现这么多颜文字还那么丑
这题 算是 树型dp经典的 小变种 了吧 。。
首先 理解一下 啥叫 树型dp,
树型树型,告诉我们 这是一个 基于树(二叉树)结构的dp
那么自然要有建树的过程。
建树 有 三种 1)单方向 2)邻接表 3)孩子兄弟
再想到dp是自下ershang
故而先计算孩子节点信息
利用孩子节点信息算出根节点信息
写出状态转移方程
通常分为 叶子节点:dp[][]
非叶子节点: dp[i][]= blablabla
这道题的状态转移方程
考虑每个节点 i为根 的sizeK的子树的最大 weight;
dp[i][sizeK]=max(dp[i][sizeK] , dp[i的孩子][sizeK-k]+dp[i][k]); ( sizeK= K ~ 1, k=sizeK~1);
最后 扫一遍 dp[i][题目指定子树大小];
ok.
#include <iostream>
#include <string.h>
#include <vector>
#define Max(a,b) (a)>(b)?(a):(b)
using namespace std;
const int maxn=110;
int f[maxn][maxn],N,K,w[maxn];
bool vis[maxn];
vector<int> node[maxn];
void dfs(int r)
{
int size=node[r].size(),i,j,t;
f[r][0]=0;
f[r][1]=w[r];
for(i = 0;i < size; i++)
{
j=node[r][i];
dfs(j);
for(j = K;j >= 1; j--)
{
for (t = j; t>=1; t--) {
f[r][j]=Max(f[r][j],f[r][t]+f[j][j-t]);
}
}
}
}
int main(void)
{
while(cin>>N>>K)
{
int i;
for (i = 0; i < N ; i++) {
cin>>w[i];
node[i].clear();
}
int a,b;
memset(vis,0,sizeof(vis));
memset(w,0,sizeof(w));
for (i = 1; i < N; i++) {
cin>>a>>b;
node[a].push_back(b);
vis[b]=true;
}
for(i = 0;i < N && vis[i] ;i++);
dfs(i);
int ans=0;
for (i = 0; i < N; i++) {
if(f[i][K]>ans) ans=f[i][K];
}
cout<<ans<<endl;
}
return 0;
}