一棵带权树,第一次经过一个节点需ti时间,获得wi的武力值
求T时间内获得的最大武力值
n,T≤300
树形dp神题(告诉了我什么叫转移顺序)
dp[i][j][0/1/2]
表示路径的 【起点终点都在i/起点(或终点)在i,另一点在i的子树内(因为路径是可逆的)/起点终点都在i的子树】 内能得到的最大武力值
转移即可(说的容易!!!)
dp[i][j][2]←dp[i][j−dis(i,v)∗2−k][2]+dp[v][k][0](v∈son[i])
dp[i][j][2]←dp[i][j−dis(i,v)∗2−k][0]+dp[v][k][2](v∈son[i])
dp[i][j][2]←dp[i][j−dis(i,v)−k][1]+dp[v][k][1](v∈son[i])
dp[i][j][1]←dp[i][j−dis(i,v)∗2−k][1]+dp[v][k][0](v∈son[i])
dp[i][j][1]←dp[i][j−dis(i,v)−k][0]+dp[v][k][1](v∈son[i])
dp[i][j][0]←dp[i][j−dis(i,v)∗2−k][0]+dp[v][k][0](v∈son[i])
注意,转移时一定一定一定要用上一个子树的状态来更新这个子树的状态(类似背包的降维优化)
注意,树边权可为0(个中含义自行体会)
#include<bits/stdc++.h>
#define LEN 350
/*中间一对地方不能反,反了的话,呵呵*/
using namespace std;
inline int getint(){
int x=0,p=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-')p=-1;
c=getchar();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x*p;
}
inline void putint(long long x){
if(x<0){
x=-x;
putchar('-');
}
static int buf[30];
int tot=0;
do{
buf[tot++]=x%10;
x/=10;
}while(x);
while(tot)putchar(buf[--tot]+'0');
}
int n,T;
struct road{
int e,nxt,len;
}r[LEN*2];
struct node{
int first,fa,w,t;
int dp[LEN][5];
}t[LEN];
int tot=1;
inline void creat(int a,int b,int c){
r[++tot].e=b;
r[tot].len=c;
r[tot].nxt=t[a].first;
t[a].first=tot;
}
int ans=0;
void dfs(int cur){
for(int i=0;i<=300;++i){
for(int j=0;j<5;++j){
t[cur].dp[i][j]=-0xfffffff;
}
}
for(int i=t[cur].t;i<=300;++i){
t[cur].dp[i][0]=t[cur].dp[i][1]=t[cur].dp[i][2]=t[cur].w;
}
for(int i=t[cur].first;i;i=r[i].nxt){
int v=r[i].e;
if(v==t[cur].fa)continue;
t[v].fa=cur;
dfs(v);
for(int j=T;j>=0;--j){ //不能反
for(int k=0;k<=T;++k){ //不能反*2
if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][2]=
max(t[cur].dp[j][2], t[cur].dp[j-r[i].len*2-k][2]+t[v].dp[k][0]);
if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][2]=
max(t[cur].dp[j][2],t[cur].dp[j-r[i].len*2-k][0]+t[v].dp[k][2]);
if(j-r[i].len-k>=t[cur].t) t[cur].dp[j][2]=
max(t[cur].dp[j][2],t[cur].dp[j-r[i].len-k][1]+t[v].dp[k][1]);
if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][1]=
max(t[cur].dp[j][1],t[cur].dp[j-r[i].len*2-k][1]+t[v].dp[k][0]);
if(j-r[i].len-k>=t[cur].t) t[cur].dp[j][1]=
max(t[cur].dp[j][1],t[cur].dp[j-r[i].len-k][0]+t[v].dp[k][1]);
if(j-r[i].len*2-k>=t[cur].t) t[cur].dp[j][0]=
max(t[cur].dp[j][0],t[cur].dp[j-r[i].len*2-k][0]+t[v].dp[k][0]);
//不能反*3
}
}
}
//cout<<cur<<endl;
for(int j=T;j>=0;--j){
//cout<<j<<" "<<t[cur].dp[j][0]<<" "<<t[cur].dp[j][1]<<" "<<t[cur].dp[j][2]<<endl;
ans=max(ans,max(t[cur].dp[j][0],(t[cur].dp[j][1],t[cur].dp[j][2])));
}
}
int main(){
n=getint(),T=getint();
bool f=1;
for(int i=1;i<=n;++i){
t[i].w=getint();
if(t[i].w)f=0;
}
if(f){
cout<<0;
return 0;
}
for(int i=1;i<=n;++i){
t[i].t=getint();
}
for(int i=1;i<n;++i){
int a=getint(),b=getint(),c=getint();
creat(a,b,c),creat(b,a,c);
}
dfs(1);
cout<<ans<<endl;
return 0;
}