//给一棵树,N个点每个点都有财宝, //要在T时间从点1到点N且能得到的最大权值 //一遍dfs记录从1到N的路径所要经过的点x个 //然后通过这一条路径将这棵树拆开x个子树 //对于这x棵子树dp[i][j]表示以i点为根的子树用时间j //最多能得到多少宝藏 //用一个分组背包可以做 #include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std ; const int maxn = 110 ; int dp[maxn][maxn*5] ; int vis[maxn] ; struct Edge { int v , w ; int next ; }edge[maxn<<1] ; int head[maxn] ; int nedge ; int n , T ; int a[maxn] ; void addedge(int u , int v , int w) { edge[nedge].v = v ; edge[nedge].w = w ; edge[nedge].next = head[u] ; head[u] = nedge++ ; } int dfs(int u , int pre) { if(u == n) { vis[n] = 1 ; return 0 ; } for(int i = head[u];i != -1 ; i = edge[i].next) { int v = edge[i].v ; if(v == pre)continue ; int tmp = dfs(v , u) ; if(tmp != -1) { vis[u] = 1 ; return tmp+edge[i].w ; } } return -1 ; } void dfss(int u , int pre) { for(int i = head[u];i != -1 ; i = edge[i].next) { int v = edge[i].v ; if(v == pre || vis[v])continue ; dfss(v , u) ; for(int j = T;j >= 2*edge[i].w;j--) for(int k = 0;k <= j-2*edge[i].w;k++) dp[u][j] = max(dp[u][j] , dp[v][k] + dp[u][j-k-edge[i].w*2]) ; } for(int i = 0;i <= T;i++) dp[u][i] += a[u] ; } int main() { //freopen("in.txt" , "r" , stdin) ; while(~scanf("%d%d" , &n , &T)) { memset(head , -1 , sizeof(head)) ; memset(vis , 0 , sizeof(vis)) ; memset(dp , 0 , sizeof(dp)) ; nedge = 0 ; for(int i = 1;i < n;i++) { int u , v , w ; scanf("%d%d%d" , &u , &v , &w) ; addedge(u , v , w) ; addedge(v , u , w) ; } for(int i = 1;i <= n;i++) scanf("%d" , &a[i]) ; int tmp = dfs(1 , -1) ; if(tmp > T) { puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!") ; continue ; } int ans = 0 ; for(int i = 1;i <= n;i++) if(vis[i]) { dfss(i , -1) ; for(int j = T;j >= 0;j--) for(int k = 0;k <= j;k++) dp[0][j] = max(dp[0][j] , dp[i][k] + dp[0][j-k]) ; } for(int i = 0;i <= T-tmp;i++) ans = max(ans , dp[0][i]) ; cout<<ans<<endl; } return 0 ; }