Problem:
Problem D
Content Delivery
You are given a computer network with n nodes. This network forms an undirected tree graph. The $i$-th edge connects the $a_i$-th node with the $b_i$-th node and its distance is $c_i$. Every node has different data and the size of the data on the $i$-th node is $s_i$. The network users can deliver any data from any node to any node. Delivery cost is defined as the product of the data size the user deliver and the distance from the source to the destination. Data goes through the shortest path in the delivery. Every node makes cache to reduce the load of this network. In every delivery, delivered data is cached to all nodes which relay the data including the destination node. From the next time of delivery, the data can be delivered from any node with a cache of the data. Thus, delivery cost reduces to the product of the original data size and the distance between the nearest node with a cache and the destination.
Calculate the maximum cost of the $m$ subsequent deliveries on the given network. All the nodes have no cached data at the beginning. Users can choose the source and destination of each delivery arbitrarily.
Input
The input consists of a single test case. The first line contains two integers $n$ $(2 \leq n \leq 2,000)$ and $m$ $(1 \leq m \leq 10^9)$. $n$ and $m$ denote the number of the nodes in the network and the number of the deliveries, respectively. The following $n - 1$ lines describe the network structure. The $i$-th line of them contains three integers $a_i$, $b_i$ $(1 \leq a_i, b_i \leq n)$ and $c_i$ $(1 \leq c_i \leq 10,000)$ in this order, which means the $a_i$-th node and the $b_i$-th node are connected by an edge with the distance $c_i$. The next line contains $n$ integers. The $j$-th integer denotes $s_j$ $(1 \leq s_j \leq 10,000)$, which means the data size of the $j$-th node. The given network is guaranteed to be a tree graph.
Output
Display a line containing the maximum cost of the $m$ subsequent deliveries in the given network.
Sample Input 1
3 2
1 2 1
2 3 2
1 10 100
Output for the Sample Input 1
320
Sample Input 2
2 100
1 2 1
1 1
Output for the Sample Input 2
2

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
#define maxn 2500
using namespace std;
int n,m;
vector<pair<int,int> > g[maxn];
long long s[maxn];
int p[maxn];
int ep[maxn];
int lb[maxn];
int rb[maxn];
long long val[maxn];
bool vis[maxn];
int t[maxn];
int rt;
int tt=1;
vector<long long> q;
pair<long long,int> seg[4*maxn];
long long lazy[4*maxn];
void dfs(int u,int pp) {
    lb[u]=rb[u]=tt;
    t[tt]=u;
    tt++;
    vis[u]=false;
    for(int i=0;i<g[u].size();i++) {
        int v=g[u][i].first;
        if(v!=pp) {
            p[v]=u;
            ep[v]=g[u][i].second;
            val[v]=val[u]+ep[v];
            dfs(v,u);
            rb[u]=rb[v];
        }
    }
}
void set_seg(int id,int l,int r) {
    lazy[id]=0;
    if(l==r) {
        seg[id]={val[t[l]],t[l]};
        return;
    }
    int m=(l+r)>>1;
    set_seg(id*2+1,l,m);
    set_seg(id*2+2,m+1,r);
    seg[id]=max(seg[id*2+1],seg[id*2+2]);
}
void propagate(int id,int l,int r) {
    if(l==r) {
        seg[id].first-=lazy[id];
        lazy[id]=0;
        return;
    }
    lazy[id*2+1]+=lazy[id];
    lazy[id*2+2]+=lazy[id];
    seg[id].first-=lazy[id];
    lazy[id]=0;
}
pair<long long,int> max_val() {
    propagate(0,1,n);
    return seg[0];
}
void update(int id,int l,int r,int x,int y,long long tv) {
    propagate(id,l,r);
    if(x<=l && r<=y) {
        lazy[id]+=tv;
        propagate(id,l,r);
        return;
    }
    if(y<l || r<x) return;
    int m=(l+r)>>1;
    update(id*2+1,l,m,x,y,tv);
    update(id*2+2,m+1,r,x,y,tv);
    seg[id]=max(seg[id*2+1],seg[id*2+2]);
}
void clear(int u) {
    if(vis[u]) return;
    vis[u]=true;
    //cout<<rt<<": "<<u<<" "<<lb[u]<<" "<<rb[u]<<" "<<endl;
    update(0,1,n,lb[u],rb[u],ep[u]);
    clear(p[u]);
}
int main() {
    int a,b,c;
    scanf("%d %d",&n,&m);
    for(int i=0;i<n-1;i++) {
        scanf("%d %d %d",&a,&b,&c);
        g[a].push_back(make_pair(b,c));
        g[b].push_back(make_pair(a,c));
    }
    for(int i=1;i<=n;i++) scanf("%lld",&s[i]);
    for(int i=1;i<=n;i++) {
        tt=1;
        rt=i;
        val[i]=0;
        dfs(i,-1);
        vis[i]=true;
        set_seg(0,1,n);
        int u=max_val().second;
        long long v=max_val().first;
        //cout<<v<<endl;
        while(v!=0) {
            q.push_back(s[i]*v);
            clear(u);
            u=max_val().second;
            v=max_val().first;
        }
    }
    sort(q.begin(),q.end());
    long long ans=0;
    while(!q.empty() && m>0) {
        ans+=q.back();
        q.pop_back();
        m--;
    }
    printf("%lld\n",ans);
	return 0;
}
accuracy: 1
time_ms: 890
memory_kb: 38116
final_rank: 17

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;

using ll = long long;
#define rep(i,n) for(ll i=0; i<ll(n); i++)


void testcase(){
    int N, M; cin >> N >> M;
    vector<vector<pair<int,ll>>> adj(N);
    rep(i,N-1){
        int u,v,w; cin >> u >> v >> w; u--; v--;
        adj[u].push_back({ v, w });
        adj[v].push_back({ u, w });
    }
    vector<ll> A(N); rep(i,N) cin >> A[i];
    vector<ll> costs;
    rep(s,N){
        auto dfs = [&](auto& dfs, int v, int p) -> ll {
            ll h = 0;
            for(auto [w,c] : adj[v]) if(w != p){
                ll d = dfs(dfs, w, v) + c;
                if(h < d) swap(h, d);
                if(d) costs.push_back(A[s]*d);
            }
            return h;
        };
        costs.push_back(dfs(dfs,s,-1) * A[s]);
    }
    sort(costs.rbegin(), costs.rend());
    ll ans = 0;
    rep(i,costs.size()) if(i<M) ans += costs[i];
    cout << ans << "\n";
}

int main(){
    cin.tie(0)->sync_with_stdio(0);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 37692
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
	ll n, k; cin >> n >> k;
	vector<vector<pair<ll, ll>>> v(n);
	rep(i, n - 1) {
		ll a, b, c;
		cin >> a >> b >> c;
		a --; b --;
		v[a].push_back({b, c});
		v[b].push_back({a, c});
	}
	vector<vector<ll>> pdp(n);
	auto dfs1 = [&](auto dfs, int now, int p) -> void {
		vector<ll> ret;
		for(auto [to, c] : v[now]) {
			if(to == p) continue;
			dfs(dfs, to, now);
			int sz = pdp[to].size();
			ret.pb(pdp[to][0] + c); 
			for(int i = 1; i < sz; i ++) {
				ret.pb(pdp[to][i]);
			}
		}
		if(ret.empty()) {
			pdp[now] = vector<ll> (1, 0);
			return;
		}
		sort(all(ret));
		reverse(all(ret));
		pdp[now] = ret;
	};
	dfs1(dfs1, 0, -1);
	vector<vector<ll>> a(n);
	auto dfs2 = [&](auto dfs, int now, int p, vector<ll> par) -> void {
		vector<ll> vec = par;
		for(auto [to, c] : v[now]) {
			if(to == p) continue;
			int sz = pdp[to].size();
			vec.pb(pdp[to][0] + c); 
			for(int i = 1; i < sz; i ++) {
				vec.pb(pdp[to][i]);
			}
		}
		sort(all(vec));
		reverse(all(vec));
		a[now] = vec;
		for(auto [to, c] : v[now]) {
			if(to == p) continue;
			vector<ll> nx = par;
			for(auto [to2, c2] : v[now]) {
				if(to == to2 or to2 == p) continue;
				int sz = pdp[to2].size();
				nx.pb(pdp[to2][0] + c2);
				for(int i = 1; i < sz; i ++) {
					nx.pb(pdp[to2][i]);
				}
			}
			if(nx.empty()) {
				nx.pb(c);
			} else {
				sort(all(nx));
				reverse(all(nx));
				nx[0] += c;
			}
			dfs(dfs, to, now, nx);
		}
	};
	dfs2(dfs2, 0, -1, vector<ll> ());
	rep(i, n) {
		ll x; cin >> x;
		for(ll &e : a[i]) e *= x;
	}
	vector<ll> vec;
	foa(vv, a) foa(e, vv) vec.pb(e);
	sort(all(vec));
	reverse(all(vec));
	ll m = min((ll)vec.size(), k);
	ll sum = 0;
	rep(i, m) sum += vec[i];
	cout << sum << endl;
    return 0;
}
accuracy: 1
time_ms: 350
memory_kb: 69664
final_rank: 15

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (ll i = (ll)(a); i < (ll)(b); i++)
#define rrep(i, a, b) for (ll i = (ll)(b)-1; i >= (ll)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N, M;
    cin >> N >> M;
    vector<vector<pair<int,ll>>> G(N);
    vector<ll> S(N);
    rep(i,0,N-1) {
        int A, B;
        ll C;
        cin >> A >> B >> C;
        A--, B--;
        G[A].push_back({B,C});
        G[B].push_back({A,C});
    }
    rep(i,0,N) cin >> S[i];
    vector<ll> X;
    auto DFS = [&](auto self, int V, int P, ll W) -> ll {
        vector<ll> Deps;
        for (auto E : G[V]) {
            auto [NV, Len] = E;
            if (NV == P) continue;
            Deps.push_back(self(self,NV,V,W) + Len);
        }
        if (Deps.empty()) {
            return 0LL;
        }
        sort(ALL(Deps));
        reverse(ALL(Deps));
        rep(i,1,Deps.size()) {
            X.push_back(Deps[i] * W);
        }
        return Deps[0];
    };
    rep(i,0,N) X.push_back(S[i] * DFS(DFS,i,-1,S[i]));
    sort(ALL(X));
    reverse(ALL(X));
    ll ANS = 0;
    rep(i,0,X.size()) {
        if (i >= M) break;
        ANS += X[i];
    }
    cout << ANS << endl;
}
accuracy: 1
time_ms: 320
memory_kb: 37940
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T> bool chmax(T& a, const T& b) { return a < b ? (a = b, 1) : 0; }
template <typename T> bool chmin(T& a, const T& b) { return a > b ? (a = b, 1) : 0; }

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    int n, m;
    cin >> n >> m;
    vector<vector<pair<int, int>>> G(n);
    rep(i,0,n-1) {
        int a, b, c;
        cin >> a >> b >> c;
        --a, --b;
        G[a].push_back({b, c});
        G[b].push_back({a, c});
    }
    vector<ll> s(n);
    for (auto& x : s) cin >> x;

    vector<ll> vals;

    auto dfs = [&](auto& dfs, int v, int p, int r) -> ll {
        vector<ll> vs(1);
        for (auto [c, w] : G[v]) {
            if (c == p) continue;
            ll x = dfs(dfs, c, v, r);
            vs.push_back(x+w);
        }
        sort(all(vs));
        reverse(all(vs));
        rep(i,1,vs.size()) vals.push_back(vs[i]*s[r]);
        return vs[0];
    };

    rep(i,0,n) {
        ll x = dfs(dfs, i, -1, i);
        vals.push_back(x*s[i]);
    }

    sort(all(vals));
    reverse(all(vals));
    ll ans = 0;
    rep(i,0,min(m, (int)vals.size())) ans += vals[i];
    cout << ans << endl;
}
accuracy: 1
time_ms: 350
memory_kb: 37940
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
#include <bitset>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,m; cin >> n >> m;
    vector<ll> cost;
    vector<vector<pair<int,int>>> g(n);
    for(int i=1;i<n;i++){
        int a,b,c; cin >> a >> b >> c;
        a--; b--;
        g[a].push_back({b,c});
        g[b].push_back({a,c});
    }
    for(int i=0;i<n;i++){
        ll S; cin >> S;
        auto dfs=[&](auto dfs,int s,int p)->ll{
            ll u = 0;
            for(auto to:g[s]){
                if(to.first == p)continue;
                ll cur = to.second+dfs(dfs,to.first,s);
                if(u < cur){
                    if(u)cost.push_back(u*S);
                    u = cur;
                }
                else{
                    if(cur)cost.push_back(cur*S);
                }
            }
            return u;
        };
        ll u = dfs(dfs,i,-1);
        cost.push_back(u*S);
    }
    sort(cost.rbegin(), cost.rend());
    ll res = 0;
    for(int i=0;i<min(m,(int)cost.size());i++){
        res += cost[i];
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 240
memory_kb: 38076
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
// clang-format off
using ll = long long;
template <class T> using V = vector<T>;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) x.begin(), x.end()
template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << "(" << p.first << ", " << p.second << ")"; }
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) { os << "[ "; for (auto &z : v) os << z << " "; os << "]"; return os; }
#ifdef _RUTHEN
#define show(x) cerr << __LINE__ << " : " << #x << " = " << x << endl;
#else
#define show(x)
#endif
// clang-format on

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll N, M;
    cin >> N >> M;
    V<V<pair<int, ll>>> G(N);
    rep(i, N - 1) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--;
        G[a].push_back({b, c});
        G[b].push_back({a, c});
    }
    V<ll> s(N);
    rep(i, N) cin >> s[i];
    V<ll> vs;
    auto rec = [&](auto self, int cur, int par, int root) -> ll {
        V<ll> ret = {0};
        for (auto &nx : G[cur]) {
            if (nx.first == par) continue;
            ret.push_back(self(self, nx.first, cur, root) + nx.second);
        }
        sort(ALL(ret));
        rep(i, (int)ret.size() - 1) vs.push_back(ret[i] * s[root]);
        return *ret.rbegin();
    };
    rep(v, N) vs.push_back(rec(rec, v, -1, v) * s[v]);
    sort(ALL(vs));
    ll ans = 0;
    while (M-- && vs.size() > 0) {
        ans += *vs.rbegin();
        vs.pop_back();
    }
    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 38056
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
// clang-format off
using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) x.begin(), x.end()
template <class T> using V = vector<T>;
template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << "(" << p.first << ", " << p.second << ")"; }
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) { os << "[ "; for (auto &z : v) os << z << " "; os << "]"; return os; }
#ifdef _RUTHEN
#define show(x) cerr << __LINE__ << " : " << #x << " = " << x << endl;
#else
#define show(x)
#endif
// clang-format on

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll N, M;
    cin >> N >> M;
    V<V<pair<int, ll>>> G(N);
    rep(i, N - 1) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--;
        G[a].push_back({b, c});
        G[b].push_back({a, c});
    }
    V<ll> s(N);
    rep(i, N) cin >> s[i];
    V<ll> vs;
    function<ll(int, int, int)> rec = [&](int cur, int par, int root) {
        V<ll> ret = {0};
        for (auto nx : G[cur]) {
            if (nx.first == par) continue;
            ret.push_back(rec(nx.first, cur, root) + nx.second);
        }
        sort(ALL(ret));
        rep(i, (int)ret.size() - 1) vs.push_back(ret[i] * s[root]);
        return *ret.rbegin();
    };
    rep(v, N) vs.push_back(rec(v, -1, v) * s[v]);
    sort(ALL(vs));
    ll ans = 0;
    while (M-- && vs.size() > 0) {
        ans += *vs.rbegin();
        vs.pop_back();
    }
    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 38084
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
// clang-format off
using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) x.begin(), x.end()
template <class T> using V = vector<T>;
template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << "(" << p.first << ", " << p.second << ")"; }
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) { os << "[ "; for (auto &z : v) os << z << " "; os << "]"; return os; }
#ifdef _RUTHEN
#define show(x) cerr << __LINE__ << " : " << #x << " = " << x << endl;
#else
#define show(x)
#endif
// clang-format on

void dfs(V<V<pair<int, ll>>> &G, int cur, int par, V<ll> &vs, ll si, V<ll> &dist) {
    V<ll> ret = {0};
    for (auto &nx : G[cur]) {
        if (nx.first == par) continue;
        dfs(G, nx.first, cur, vs, si, dist);
        ret.push_back(dist[nx.first] + nx.second);
    }
    sort(ALL(ret));
    dist[cur] = *ret.rbegin();
    if (par != -1) ret.pop_back();
    for (auto &di : ret) vs.push_back(di * si);
    return;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll N, M;
    cin >> N >> M;
    V<V<pair<int, ll>>> G(N);
    rep(i, N - 1) {
        int a, b, c;
        cin >> a >> b >> c;
        a--, b--;
        G[a].push_back({b, c});
        G[b].push_back({a, c});
    }
    V<ll> s(N);
    rep(i, N) cin >> s[i];
    V<ll> vs;
    rep(v, N) {
        V<ll> dist(N, 0);
        dfs(G, v, -1, vs, s[v], dist);
    }
    sort(ALL(vs));
    ll ans = 0;
    while (M-- && vs.size() > 0) {
        ans += *vs.rbegin();
        vs.pop_back();
    }
    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 38060
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define inc(i, a, b) for (int i = (a); i <= (b); ++i)
#define dec(i, a, b) for (int i = (a); i >= (b); --i)

int main() {
    ll n, m;
    cin >> n >> m;
    vector<pair<ll, ll>> g[n];
    rep(i, n - 1) {
        ll a, b, c;
        cin >> a >> b >> c, a--, b--;
        g[a].push_back({b, c});
        g[b].push_back({a, c});
    }
    vector<ll> a(n);
    rep(i, n) cin >> a[i];
    vector<ll> ans;

    function<ll(ll, ll, ll)> dfs = [&](ll v, ll p, ll r) {
        vector<ll> ds;
        for (auto [u, c] : g[v]) {
            if (u == p) continue;
            ds.push_back(dfs(u, v, r) + c);
        }
        if (ds.empty()) return 0LL;
        sort(ds.begin(), ds.end(), greater<ll>());
        rep(i, (int) ds.size() - 1) ans.push_back(ds[i + 1] * a[r]);
        return ds[0];
    };

    rep(i, n) ans.push_back(dfs(i, -1, i) * a[i]);
    sort(ans.begin(), ans.end(), greater<ll>());
    cout << accumulate(ans.begin(), ans.begin() + min(m, (ll) ans.size()), 0LL) << endl;
}
accuracy: 1
time_ms: 320
memory_kb: 37816
final_rank: 6

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long int MOD = 1000000007;
constexpr long long int MOD = 998244353;
constexpr long double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

void func(vector<vector<pair<int, int>>>& edge, vector<int>& num, priority_queue<long long>& Q, long long by, int node, int p = -1) {
	int mx = 0;
	for (auto i : edge[node]) {
		if (i.first == p)continue;
		func(edge, num, Q, by, i.first, node);
		num[i.first] += i.second;
	//	cout << node << " " << i.first << " " << i.second << endl;
		if (mx == 0) {
			mx = num[i.first];
		}
		else {
			if (mx < num[i.first]) {
				Q.push(mx * by);
				mx = num[i.first];
			}
			else {
				Q.push(num[i.first] * by);
			}
		}
	}
	if (p == -1) {
		Q.push(mx * by);
	}
	num[node] = mx;
	return;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N >> M;
	vector<vector<pair<int, int>>>edge(N);
	for (int i = 1; i < N; i++) {
		cin >> L >> R >> K;
		L--, R--;
		edge[L].push_back({ R,K });
		edge[R].push_back({ L,K });
	}
	vector<long long>v(N);
	for (auto& i : v)cin >> i;
	priority_queue<long long>PQ;
	for (int i = 0; i < N; i++) {
		vector<int>num(N);
		func(edge, num, PQ, v[i], i);
	}
	long long ans = 0;
	while (PQ.size() && M) {
		M--;
		ans += PQ.top();
		PQ.pop();
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 510
memory_kb: 37804
final_rank: 14

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

ll solve(int n, int m) {
	graph<ll> g(n);
	g.input(n - 1, false, true, 1);
	VEC(ll, weight, n);

	debug(weight);

	function<vll(vll, vll)> merge = [](vll a, vll b) {
		if(a.size() < b.size()) swap(a, b);
		if(a[0] < b[0]) swap(a[0], b[0]);
		foa(t, b) a.push_back(t);
		return a;
	};
	function<vll(int, vll, ll)> send = [&](int id, vll predata, ll len) {
		predata[0] += len;
		return predata;
	};
	vll unit = {0};

	vector<vll> res = g.ReRootingDP(unit, merge, send);

	debug(res);

	vll vals;
	rep(i, n) {
		foa(t, res[i]) {
			if(t) vals.push_back(t * weight[i]);
		}
	}

	sort(rall(vals));
	return accumulate(vals.begin(), vals.begin() + min(m, int(vals.size())), 0LL);
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n, m;
	while(cin >> n >> m) {
		cout << solve(n, m) << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 159716
final_rank: 20

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

ll solve(int n, int m) {
	graph<ll> g(n);
	g.input(n - 1, false, true, 1);
	VEC(ll, weight, n);

	debug(weight);

	function<vll(vll, vll)> merge = [](vll a, vll b) {
		if(a.size() < b.size()) swap(a, b);
		if(a[0] < b[0]) swap(a[0], b[0]);
		foa(t, b) a.push_back(t);
		return move(a);
	};
	function<vll(int, vll, ll)> send = [&](int id, vll predata, ll len) {
		predata[0] += len;
		return move(predata);
	};
	vll unit = {0};

	vector<vll> res = g.ReRootingDP(unit, merge, send);

	debug(res);

	vll vals;
	rep(i, n) {
		foa(t, res[i]) {
			if(t) vals.push_back(t * weight[i]);
		}
	}

	sort(rall(vals));
	return accumulate(vals.begin(), vals.begin() + min(m, int(vals.size())), 0LL);
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n, m;
	while(cin >> n >> m) {
		cout << solve(n, m) << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 159684
final_rank: 19

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

ll solve(int n, int m) {
	graph<ll> g(n);
	g.input(n - 1, false, true, 1);
	VEC(ll, weight, n);

	debug(weight);

	function<vll(vll, vll)> merge = [](vll a, vll b) {
		if(a.size() < b.size()) swap(a, b);
		if(a[0] < b[0]) swap(a[0], b[0]);
		foa(t, b) a.push_back(t);
		return move(a);
	};
	function<vll(int, vll, ll)> send = [&](int id, vll predata, ll len) {
		predata[0] += len;
		return move(predata);
	};
	vll unit = {0};

	vector<vll> res = g.ReRootingDP(unit, merge, send);

	debug(res);

	vll vals;
	rep(i, n) {
		foa(t, res[i]) {
			if(t) vals.push_back(t * weight[i]);
		}
	}

	sort(rall(vals));
	debug(vals);
	debug(m, vals.size());
	chmin(m, (int)vals.size());
	ll ans = 0;
	rep(i, m) ans += vals[i];
	debug(ans);
	return ans;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n, m;
	while(cin >> n >> m) {
		ll res = solve(n, m);
		debug(res);
		cout << res << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 159668
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;

void dfs1(vector<vector<pair<int, ll>>> &G, vector<vector<pair<int, ll>>> &H, vector<ll> &dp, vector<int> &leaf, int u) {
  dp[u] = 0;
  for (int i = 0; i < G[u].size(); i++) {
    if (dp[G[u][i].first] == -1) {
      H[G[u][i].first].emplace_back(make_pair(u, G[u][i].second));
      dfs1(G, H, dp, leaf, G[u][i].first);
      dp[u] = max(dp[u], dp[G[u][i].first] + G[u][i].second);
    }
  }
  if (dp[u] == 0) leaf.emplace_back(u);
  return;
}

ll dfs2(vector<vector<pair<int, ll>>> &H, vector<ll> &dp, vector<bool> &used, int u) {
  ll res = 0;
  while (H[u].size() > 0 && !used[u]) {
    res += H[u][0].second;
    used[u] = true;
    if (dp[H[u][0].first] == dp[u] + H[u][0].second) u = H[u][0].first;
    else break;
  }
  return res;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, m;
  cin >> n >> m;

  vector<vector<pair<int, ll>>> G(n);
  for (int i = 0; i < n - 1; i++) {
    int a, b;
    ll c;
    cin >> a >> b >> c;
    a--;
    b--;
    G[a].emplace_back(make_pair(b, c));
    G[b].emplace_back(make_pair(a, c));
  }

  vector<ll> s(n);
  for (int i = 0; i < n; i++) cin >> s.at(i);

  vector<ll> x;
  for (int i = 0; i < n; i++) {
    vector<vector<pair<int, ll>>> H(n);
    vector<ll> dp(n, -1); // dp[i]: iを根とする部分木の高さ
    vector<int> leaf;
    dfs1(G, H, dp, leaf, i);
    vector<bool> used(n, false); // used[i]: iから親方向に出ている辺を使ったかどうか
    for (int j = 0; j < (int) leaf.size(); j++) {
      ll tmp = dfs2(H, dp, used, leaf.at(j));
      x.emplace_back(tmp * s.at(i));
    }
  }

  sort(x.rbegin(), x.rend());

  ll ans = 0;
  for (int i = 0; i < min<int>(m, x.size()); i++) {
    ans += x.at(i);
  }

  cout << ans << '\n';
}
accuracy: 1
time_ms: 430
memory_kb: 38008
final_rank: 13

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
const int mod = 1e9 + 7;
//const int mod = 998244353;

int main(){
	int n,m; cin >> n >> m;
	vector<vpl> G(n);
	rep(i,n-1){
		int a,b,c; cin >> a >> b >> c; a--; b--;
		G[a].emplace_back(b,c);
		G[b].emplace_back(a,c);
	}
	vl s(n); rep(i,n) cin >> s[i];
	priority_queue<ll> pq;
	auto dfs = [&](auto &&dfs, int u, int p, int id) -> ll {
		vl L(1,0);
		for(auto v : G[u]){
			if(v.first == p) continue;
			L.push_back(dfs(dfs,v.first,u,id)+v.second);
		}
		sort(rall(L));
		REP(i,1,L.size()){
			pq.push(L[i]*s[id]);
		}
		return L[0];
	};
	rep(i,n){
		pq.push(dfs(dfs,i,-1,i)*s[i]);
	}
	ll ans = 0;
	rep(i,m){
		if(pq.empty()) break;
		ans += pq.top(); pq.pop();
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 630
memory_kb: 37788
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define POPCOUNT(x) __builtin_popcount(x)
template <typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template <typename T> void chmax(T &a, const T &b) { a = max(a, b); }

const ll INF = 1LL << 60;

struct FastIO {
    FastIO() {
        cin.tie(0);
        ios::sync_with_stdio(0);
    }
} fastiofastio;

const ll MOD = 1e9 + 7;

// BEGIN CUT
ll modpow(ll x, ll y, ll m) {
    ll a = 1, p = x;
    while (y > 0) {
        if (y % 2 == 0) {
            p = (p * p) % m;
            y /= 2;
        } else {
            a = (a * p) % m;
            y--;
        }
    }
    return a;
}
// END CUT

ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

vector<PII> G[2000];
vector<ll> vec;
ll s[2000];

ll solve(int v, int par, int root) {
    ll ma = 0;
    for (auto [to, cost] : G[v]) {
        if (to == par)
            continue;
        ll ret = solve(to, v, root);
        ret += cost;
        if (ma <= ret) {
            vec.push_back(ma * s[root]);
            ma = ret;
        } else {
            vec.push_back(ret * s[root]);
        }
    }
    return ma;
}

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n - 1; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        a--;
        b--;
        G[a].emplace_back(b, c);
        G[b].emplace_back(a, c);
    }
    for (int i = 0; i < n; i++)
        cin >> s[i];
    for (int i = 0; i < n; i++) {
        ll ret = solve(i, -1, i);
        vec.push_back(ret * s[i]);
    }
    sort(ALL(vec), greater<ll>());
    m = min(m, (int)vec.size());
    ll ans = 0;
    for (int i = 0; i < m; i++) {
        ans += vec[i];
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 250
memory_kb: 38240
final_rank: 3

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N,M;
vector<pair<int,int> >G[2000];
vector<long>A;
int dfs(int u,int p,int S)
{
	int mx=0;
	for(pair<int,int>e:G[u])
	{
		int v=e.first;
		if(v!=p)
		{
			int now=dfs(v,u,S);
			now+=e.second;
			if(mx<now)
			{
				if(mx>0)A.push_back((long)S*mx);
				mx=now;
			}
			else
			{
				A.push_back((long)S*now);
			}
		}
	}
	return mx;
}
int main()
{
	cin>>N>>M;
	for(int i=1;i<N;i++)
	{
		int a,b,c;cin>>a>>b>>c;
		a--,b--;
		G[a].push_back(make_pair(b,c));
		G[b].push_back(make_pair(a,c));
	}
	for(int i=0;i<N;i++)
	{
		int S;cin>>S;
		int now=dfs(i,-1,S);
		A.push_back((long)S*now);
	}
	sort(A.begin(),A.end());
	if(M>A.size())M=A.size();
	long ans=0;
	for(int i=0;i<M;i++)ans+=A[A.size()-1-i];
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 250
memory_kb: 37900
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
int main(){
  int n, m;
  cin >> n >> m;
  vector<vector<pair<int, int>>> E(n);
  for (int i = 0; i < n - 1; i++){
    int a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    E[a].push_back(make_pair(c, b));
    E[b].push_back(make_pair(c, a));
  }
  vector<int> s(n);
  for (int i = 0; i < n; i++){
    cin >> s[i];
  }
  vector<long long> cost;
  for (int i = 0; i < n; i++){
    vector<int> p(n, -1);
    vector<vector<pair<int, int>>> c(n);
    vector<int> b;
    queue<int> Q;
    Q.push(i);
    while (!Q.empty()){
      int v = Q.front();
      Q.pop();
      b.push_back(v);
      for (auto P : E[v]){
        int w = P.second;
        if (w != p[v]){
          p[w] = v;
          c[v].push_back(P);
          Q.push(w);
        }
      }
    }
    reverse(b.begin(), b.end());
    vector<long long> dp(n, 0);
    for (int v : b){
      for (auto &P : c[v]){
        int w = P.second;
        dp[w] += P.first;
        if (dp[w] > dp[v] && P != c[v][0]){
          swap(c[v][0], P);
        }
        dp[v] = max(dp[v], dp[w]);
      }
    }
    cost.push_back(s[i] * dp[i]);
    for (int v : b){
      for (auto P : c[v]){
        if (P != c[v][0]){
          int w = P.second;
          cost.push_back(s[i] * dp[w]);
        }
      }
    }
  }
  sort(cost.begin(), cost.end(), greater<long long>());
  int cnt = cost.size();
  long long ans = 0;
  for (int i = 0; i < min(m, cnt); i++){
    ans += cost[i];
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 410
memory_kb: 35928
final_rank: 12

code_snippet: #pragma GCC optimize("Ofast")
//#pragma GCC target ("sse4")

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 18;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

struct edge {
	int to, cost;
};
void solve() {
	int n, m; cin >> n >> m;
	vector<vector<edge>> G(n);
	rep(i, n - 1) {
		int a, b, c; cin >> a >> b >> c;
		a--; b--;
		G[a].push_back({ b,c });
		G[b].push_back({ a,c });
	}
	vector<int> s(n);
	vector<ll> costs;
	rep(i, n) {
		cin >> s[i];
	}
	rep(i, n) {
		vector<int> dists;
		function<int(int, int)>dfs = [&](int id, int fr)->int {
			vector<int> nexs;
			for (edge e : G[id])if (e.to != fr) {
				nexs.push_back(e.cost + dfs(e.to, id));
			}
			int ma = 0, loc = -1;
			rep(j, nexs.size()) {
				if (nexs[j] > ma) {
					ma = nexs[j];
					loc = j;
				}
			}
			rep(j, nexs.size())if (j != loc) {
				dists.push_back(nexs[j]);
			}
			return ma;
		};
		dists.push_back(dfs(i, -1));
		for (int d : dists) {
			costs.push_back((ll)d * s[i]);
			//cout << "? " << i << " " << d << "\n";
		}
	}
	sort(all(costs),greater<ll>());
	ll ans = 0;
	m = min(m, (int)costs.size());
	rep(i, m)ans += costs[i];
	cout << ans << "\n";
}

signed main() {
	//ios::sync_with_stdio(false);
	//cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();

	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 41904
final_rank: 5