设 t 为根节点到某一叶子节点路径上的权值和,则应让最小的 t 尽量的大。
坑点在于存在价格为零的商品。
一维倒序递推就失去了意义,无法保证每组选且只选一个。
另外可以选择不建立任何塔防,也就是说每个节点都多了一个price和power均为零的商品。
dp[s][k] 表示在 s 姐点投入 k 时所能取得的最大值。
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long LL
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007
#define LM(a,b) (((ULL)(a))<<(b))
#define RM(a,b) (((ULL)(a))>>(b))
using namespace std;
const LL MAXN = 1010;
struct N
{
int u,v,w,next;
}edge[MAXN*2];
int head[MAXN];
int Top;
void Link(int u,int v,int w = -1)
{
edge[Top].u = u;
edge[Top].v = v;
edge[Top].w = w;
edge[Top].next = head[u];
head[u] = Top++;
}
void Init_head_Top(int n)
{
memset(head,-1,sizeof(int)*(n+2));
Top = 0;
}
struct Pro
{
int c,w;
}p[1010][53];
int top[1010];
int dp[1010][210];
void dfs(int s,int pre,int m)
{
int i,j,k;
int val[2][210];
memset(val,-1,sizeof(val));
int site = 1;
for(k = head[s];k != -1;k = edge[k].next)
{
if(edge[k].v != pre)
{
dfs(edge[k].v,s,m);
memset(val[site&1],-1,sizeof(val[site&1]));
if(site == 1)
{
for(j = 0;j <= m; ++j)
val[site&1][j] = dp[edge[k].v][j];
}
else
{
for(i = m;i >= 0; --i)
{
if(val[(site-1)&1][i] != -1)
{
for(j = m-i;j >= 0; --j)
{
if(dp[edge[k].v][j] != -1)
{
val[site&1][i+j] = max(val[site&1][i+j],min(val[(site-1)&1][i],dp[edge[k].v][j]));
}
}
}
}
}
site++;
}
}
// printf("s = %d : \n",s);
//
// for(j = 0;j <= m; ++j)
// {
// if(val[(site-1)&1][j] >= 0)
// {
// printf("c = %d w = %d\n",j,val[(site-1)&1][j]);
// }
// }
for(i = m; i>= 0; --i)
{
if(val[(site-1)&1][i] != -1)
{
for(j = 0;j < top[s]; ++j)
{
if(i + p[s][j].c <= m)
{
dp[s][i+p[s][j].c] = max(dp[s][i+p[s][j].c],val[(site-1)&1][i] + p[s][j].w);
}
}
}
}
for(i = 0;i < top[s] ; ++i)
{
if(p[s][i].c <= m)
dp[s][p[s][i].c] = max(dp[s][p[s][i].c],p[s][i].w);
}
}
int main()
{
int T;
int n,m;
int i,j,u,v;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
Init_head_Top(n);
for(i = 1;i < n; ++i)
{
scanf("%d %d",&u,&v);
Link(u,v);
Link(v,u);
}
scanf("%d",&m);
memset(dp,-1,sizeof(dp));
for(i = 1;i <= n; ++i)
{
scanf("%d",&top[i]);
for(j = 0;j < top[i]; ++j)
{
scanf("%d %d",&p[i][j].c,&p[i][j].w);
}
p[i][j].c = 0 , p[i][j].w = 0;
top[i]++;
}
dfs(1,-1,m);
int Max = 0;
// for(i = 1;i <= n; ++i)
// {
// printf("i = %d : \n",i);
// for(j = 0;j <= m; ++j)
// {
// if(dp[i][j] > 0)
// printf("c = %d w = %d\n",j,dp[i][j]);
// }
// puts("");
// }
for(i = 0;i <= m; ++i)
{
Max = max(Max,dp[1][i]);
}
printf("%d\n",Max);
}
return 0;
}