由于初中玩泥巴。到现在好像都不是很懂泛化背包那一套理论,但是某位大爷教了我一个很迷的dfs序dp....
代码还是非常简单的。但是这里的f[i][j]表示的却是正在考虑i节点,已经用掉了j个节点。。。(这句话我也思考了很久,结论是这个正在考虑确实很玄妙,,,首先i号节点肯定是没选,但是他又肯定是要值得去被考虑的。这句话还是看了代码自己领悟吧。。鬼畜的dp状态可以简化一下本来分类讨论到欲仙欲死的题目)
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#define pb push_back
#define forup(i,a,b) for(int i=(a);i<=(b);i++)
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)
#define maxn 3005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline
void read(T& num){ num = 0; bool f = true;char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();} while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();} num = f ? num: -num; }
int out[100];
template<class T> inline
void write(T x,char ch){ if (x==0) {putchar('0'); putchar(ch); return;} if (x<0) {putchar('-'); x=-x;}int num=0; while (x){ out[num++]=(x%10); x=x/10;} fordown(i,num-1,0) putchar(out[i]+'0'); putchar(ch); }
/*==================split line==================*/
int n,lim;
int cnt;
int chu[maxn];
int val[maxn];
int que[maxn*10];
int f[maxn][maxn];
vector<int> g[maxn];
void dfs(int x,int fa)
{ cnt++; que[cnt]=x;
for(int i=0;i<g[x].size();i++) { int v=g[x][i]; if(v!=fa) dfs(v,x); }
chu[x]=cnt;
}
int main()
{ cin>>n>>lim;
forup(i,1,n) read(val[i]);
forup(i,1,n-1){int x,y; read(x);read(y);g[x].pb(y); g[y].pb(x); }
dfs(1,0);
forup(i,0,n) forup(j,0,n) f[i][j]=-INF;
f[1][0]=0;
forup(i,1,cnt)
forup(j,0,lim)
{
f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+val[que[i]]);
f[chu[que[i]]+1][j]=max(f[chu[que[i]]+1][j],f[i][j]);
}
/* forup(i,1,cnt+1) cout<<que[i]<<' ';cout<<endl;
forup(i,1,cnt)
forup(j,1,lim)
{ cout<<"f["<<i<<"]["<<j<<"]="<<f[i][j]<<endl;
}*/
int cmax=-INF;
forup(i,1,lim) cmax=max(cmax,f[cnt+1][i]);
cout<<cmax;
return 0;
}