#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define FOR(i,a,b) for (int i=(a),for_##i##_max=(b);i<=(for_##i##_max);++i) #define RFOR(i,a,b) for (int i=(a),rfor_##i##_min=(b);i>=(rfor_##i##_min);--i) #define REP(i,n) for (int i=0,rep_##i##_len=(n);i<(rep_##i##_len);++i) #define RREP(i,n) for (int i=(n)-1;i>=0;--i) namespace { // Basics template void chmin(T &x, T y) { x = std::min(x, y); } template void chmax(T &x, T y) { x = std::max(x, y); } template __attribute__((unused)) const auto minimum = static_cast(std::min); template __attribute__((unused)) const auto maximum = static_cast(std::max); template int cmp3(T lhs, T rhs) { return (lhs == rhs) ? 0 : (lhs > rhs) ? 1 : -1; } template __attribute__((unused)) T constexpr infty = std::numeric_limits::max / 3; template<> __attribute__((unused)) auto constexpr infty = 1'100'100'100; template<> __attribute__((unused)) auto constexpr infty = 100'500'400'300'200'100LL; using lli = long long int; using ld = long double; } // namespace namespace { // Graph Basics template struct edge { int from, to; WeightT weight; edge(int s, int d, WeightT w): from(s), to(d), weight(w) {} }; template bool operator< (edge const &lhs, edge const &rhs) { if (lhs.weight != rhs.weight) { return lhs.weight < rhs.weight; } else if (lhs.from != rhs.from) { return lhs.from < rhs.from; } return lhs.to < rhs.to; } template using edges = std::vector >; template using adjacency_list = std::vector >; template void add_undir_edge(adjacency_list &G, int u, int v, WeightT w) { G[u].emplace_back(u, v, w); G[v].emplace_back(v, u, w); } template adjacency_list inverse_graph(adjacency_list const &G) { size_t const n = G.size(); adjacency_list F(n); for (auto &&es: G) for (auto &&e: es) { F[e.to].emplace_back(e.to, e.from, e.weight); } return F; } template edges all_edges(adjacency_list const &G) { auto const E = std::accumulate(begin(G), end(G), 0, [](auto x, auto vec) { return x + vec.size(); }); edges es; es.reserve(E); for (auto &&vec: G) { std::copy(begin(vec), end(vec), std::back_inserter(es)); } return es; } } // namespace namespace { // rooted_tree template struct rooted_tree { size_t size; std::vector topo; std::vector par; std::vector> children; }; template rooted_tree make_rooted_tree(adjacency_list const &G, size_t root) { size_t N = G.size(); std::vector topo, par(N); par[root] = N + 1; std::vector> ch(N); std::vector used(N, false); std::stack stk; stk.push(root); used[root] = true; while (!stk.empty()) { size_t const u = stk.top(); stk.pop(); topo.push_back(u); for (auto &&e : G[u]) { if (used[e.to]) { continue; } stk.push(e.to); used[e.to] = true; par[e.to] = u; ch[u].push_back(e); } } return { N, topo, par, ch }; } } // namespace using namespace std; using Graph = adjacency_list; void solve(int N, int M, vector Us, Graph const &G) { auto const tree = make_rooted_tree(G, 0); vector> dp(N, vector(M+1, 0)); REP(u, N) FOR(t, 0, M) { dp[u][t] = Us[u]; } RREP(i, N) { int u = tree.topo[i]; for (auto &&e : tree.children[u]) { RFOR(t, M, 2*e.weight) FOR(s, 0, t-2*e.weight) { chmax(dp[u][t], dp[u][s]+dp[e.to][t-s-2*e.weight]); } } } cout << dp[0][M] << endl; } int main() { int N, M; cin >> N >> M; Graph G(N); vector Us; REP(i, N) { lli U; cin >> U; Us.push_back(U); } REP(i, N-1) { lli A, B, C; cin >> A >> B >> C; add_undir_edge(G, A, B, C); } solve(N, M, Us, G); return 0; }