由於初中玩泥巴。到現在好像都不是很懂泛化揹包那一套理論,但是某位大爺教了我一個很迷的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;
}