#include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
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()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

// insertしてbuildしたあとprocessでクエリを進めていく
struct Mo {
    int width;
    int nl, nr, ptr;
    vector<bool> used;
    vector<int> left, right, order;
    using F = function<void(int)>;
    F add, del;

    inline void distribute(int idx) {
        used[idx].flip();
        if(used[idx]) add(idx);
        else del(idx);
    }

    Mo(int n, F a, F d) : width((int)sqrt(n)), nl(0), nr(0), ptr(0), used(n), add(a), del(d) {}

    // [l, r)
    void insert(int l, int r) {
        left.push_back(l);
        right.push_back(r);
    }
    void build() {
        order.resize(left.size());
        iota(ALL(order), 0);
        sort(ALL(order), [&](int a, int b) {
            if(left[a] / width != left[b] / width) return left[a] < left[b];
            return right[a] < right[b];
        });
    }
    // クエリを1つ進め、クエリのidを返す
    int process() {
        if(ptr == (ll)order.size()) return -1;
        const auto id = order[ptr];
        while(nl > left[id]) distribute(--nl);
        while(nr < right[id]) distribute(nr++);
        while(nl < left[id]) distribute(nl++);
        while(nr > right[id]) distribute(--nr);
        return order[ptr++];
    }
};

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

    ll n, q;
    cin >> n >> q;
    struct edge { ll to, col, dist; };
    vector<vector<edge>> g(n);
    map<PII, ll> color, distance;
    REP(i, n-1) {
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        a--, b--, c--;
        g[a].push_back({b, c, d});
        g[b].push_back({a, c, d});
        PII e(a, b);
        if(e.first > e.second) swap(e.first, e.second);
        color[e] = c;
        distance[e] = d;
    }

    // オイラーツアー
    ll ptr = 1;
    vector<ll> tour(2*n-1), in(n);
    function<void(ll,ll)> euler_tour = [&](ll v, ll p) {
        in[v] = ptr-1;
        for(auto to: g[v]) {
            if(to.to == p) continue;
            tour[ptr++] = to.to;
            euler_tour(to.to, v);
        }
        if(p != -1) tour[ptr++] = p;
    };
    euler_tour(0, -1);

    struct node {
        ll idx, col, d;
    };

    ll mp_idx = 0;
    map<PII,node> mp;
    FOR(i, 1, 2*n-1) {
        PII e({tour[i-1], tour[i]});
        if(e.first > e.second) swap(e.first, e.second);
        if(mp.find(e) == mp.end()) mp[e] = {mp_idx++, color[e], distance[e]};
    }
    vector<node> v_edge(2*n-2);
    FOR(i, 1, 2*n-1) {
        PII e(tour[i-1], tour[i]);
        if(e.first > e.second) swap(e.first, e.second);
        v_edge[i-1] = mp[e];
    }

    ll sum = 0;
    vector<ll> cnt(n), dist(n);
    vector<int> parity(n-1);
    auto  f = [&](ll idx) {
        // tour[idx+1], tour[idx] → 辺番号, col, d
        ll e = v_edge[idx].idx, col = v_edge[idx].col, d = v_edge[idx].d;
        parity[e] = 1 - parity[e];
        if(parity[e]) {
            sum += d;
            cnt[col]++;
            dist[col] += d;
        } else {
            sum -= d;
            cnt[col]--;
            dist[col] -= d;
        }
    };
    Mo mo(2*n-1, f, f);

    vector<ll> x(q), y(q), u(q), v(q);
    REP(i, q) {
        cin >> x[i] >> y[i] >> u[i] >> v[i];
        u[i]--, v[i]--, x[i]--;
        ll ta = in[u[i]], tb = in[v[i]];
        if(ta > tb) swap(ta, tb);
        // パスa,bについてのクエリは[in[a],in[b])を見る
        mo.insert(ta, tb);
    }
    mo.build();

    vector<ll> ans(q);
    REP(i, q) {
        ll idx = mo.process();
        // cout << idx << " " << x[idx] << " " << y[idx] << " " << sum << endl;
        // cout << cnt << endl;
        // cout << dist << endl;
        // cout << dist[x[idx]] << " " << cnt[x[idx]] << " " << y[idx] << endl;
        ans[idx] = sum - dist[x[idx]] + cnt[x[idx]] * y[idx];
    }
    REP(i, q) cout << ans[i] << "\n";

    return 0;
}


Measured memory_bytes: 49012