题目链接:hihocoder1055
【分析】用背包的思想进行树形DP,注意如果要选择该子树根是必须要选择的,否则无法和下面的连通。
【AC CODE】0ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <map> //#include <unordered_map> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 100+10, MAXM = 100*2+10; int head[MAXN], tol, nxt[MAXM], to[MAXM]; int val[MAXN], dp[MAXN][MAXN], m, num[MAXN]; inline void add_edge(int u, int v) { nxt[tol] = head[u], to[tol] = v; head[u] = tol++; } void dfs(int u, int fa) { repe(i,1,m) dp[u][i] = val[u]; for(int i = head[u]; ~i; i = nxt[i]) { int v = to[i]; if(fa == v) continue; dfs(v,u); num[u] += num[v]; int mx = min(num[v],m); int tmp[MAXN]; memcpy(tmp,dp[u],sizeof(dp[u])); repe(j,1,mx)//v子树取j个点 { repe(k,j+1,m)//u树取k个 tmp[k] = max(tmp[k], dp[u][k-j]+dp[v][j]); } repe(i,0,m) dp[u][i] = max(dp[u][i], tmp[i]); } num[u]++; } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif int n; while(~scanf("%d %d%*c", &n, &m)) { repe(i,1,n) scanf("%d%*c", &val[i]); clc(head,-1); tol = 0; rep(i,1,n) { int u,v; scanf("%d %d%*c", &u, &v); add_edge(u,v); add_edge(v,u); } clc(dp,0); clc(num,0); dfs(1,-1); printf("%d\n", dp[1][m]); } return 0; }