#include"bits/stdc++.h"
#include<unordered_set>
#include<unordered_map>
#include<random>
using namespace std;
typedef long long ll;
const ll MOD = (ll)(1e9+7);
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int (i)=0; (i)<(int)(n); (i)++)
int dx[4]={ 1,0,-1,0 };
int dy[4]={ 0,1,0,-1 };

struct RSQ{
private:
    int N;
    vector<long long> node, lazy;
    vector<bool> lazyFlg;
    long long DEFAULT;
public:
    void init(int n, long long def=0LL){
        DEFAULT = def;
        node.clear();
        lazy.clear();
        lazyFlg.clear();
        N = 1;
        while(N < n) N = (N<<1);
        for(int i=0; i<2*N-1; i++){
            node.push_back(DEFAULT);
            lazy.push_back(0LL);
            lazyFlg.push_back(false);
        }
    }
    void eval(int k, int l, int r){
        if(lazyFlg[k]){
            node[k] = lazy[k];
            if(r-l > 1){
                lazy[(k<<1)+1] = lazy[k] >> 1;
                lazyFlg[(k<<1)+1] = true;
                lazy[(k<<1)+2] = lazy[k] >> 1;
                lazyFlg[(k<<1)+2] = true;
            }
            lazy[k] = 0LL;
            lazyFlg[k] = false;
        }
        else{
            node[k] += lazy[k];
            if(r-l > 1){
                lazy[(k<<1)+1] += lazy[k] >> 1;
                lazy[(k<<1)+2] += lazy[k] >> 1;
            }
            lazy[k] = 0LL;
        }
    }
    void update(int a, long long x){
        update(a, a+1, x);
    }
    void update(int a, int b, long long x, int k=0, int l=0, int r=-1){
        if(a >= b) return;
        if(r == -1) r = N;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b){
            lazy[k] = x * (r-l);
            lazyFlg[k] = true;
            eval(k, l, r);
        }
        else{
            update(a, b, x, (k<<1)+1, l, (l+r)>>1);
            update(a, b, x, (k<<1)+2, (l+r)>>1, r);
            node[k] = node[(k<<1)+1] + node[(k<<1)+2];
        }
    }
    void add(int a, long long x){
        add(a, a+1, x);
    }
    void add(int a, int b, long long x, int k=0, int l=0, int r=-1){
        if(a >= b) return;
        if(r == -1) r = N;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b){
            lazy[k] += x * (r-l);
            eval(k, l, r);
        }
        else{
            add(a, b, x, (k<<1)+1, l, (l+r)>>1);
            add(a, b, x, (k<<1)+2, (l+r)>>1, r);
            node[k] = node[(k<<1)+1] + node[(k<<1)+2];
        }
    }
    long long sum(int a, int b, int k=0, int l=0, int r=-1){
        if(a >= b) 0LL;
        if(r == -1) r = N;
        if(b <= l || r <= a) return 0LL;
        eval(k, l, r);
        if(a <= l && r <= b) return node[k];
        return sum(a, b, (k<<1)+1, l, (l+r)>>1) + sum(a, b, (k<<1)+2, (l+r)>>1, r);
    }
};

struct RMinQ{
private:
    int N;
    vector<long long> node, lazy;
    vector<bool> lazyFlg;
    long long DEFAULT;
public:
    void init(int n, long long def=9223372036854775807LL){
        DEFAULT = def;
        node.clear();
        lazy.clear();
        lazyFlg.clear();
        N = 1;
        while(N < n) N = (N<<1);
        for(int i=0; i<2*N-1; i++){
            node.push_back(DEFAULT);
            lazy.push_back(0LL);
            lazyFlg.push_back(false);
        }
    }
    void eval(int k, int l, int r){
        if(lazyFlg[k]){
            node[k] = lazy[k];
            if(r-l > 1){
                lazy[(k<<1)+1] = lazy[k];
                lazyFlg[(k<<1)+1] = true;
                lazy[(k<<1)+2] = lazy[k];
                lazyFlg[(k<<1)+2] = true;
            }
            lazy[k] = 0LL;
            lazyFlg[k] = false;
        }
        else{
            node[k] += lazy[k];
            if(r-l > 1){
                lazy[(k<<1)+1] += lazy[k];
                lazy[(k<<1)+2] += lazy[k];
            }
            lazy[k] = 0LL;
        }
    }
    void update(int a, long long x){
        update(a, a+1, x);
    }
    void update(int a, int b, long long x, int k=0, int l=0, int r=-1){
        if(a >= b) return;
        if(r == -1) r = N;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b){
            lazy[k] = x;
            lazyFlg[k] = true;
            eval(k, l, r);
        }
        else{
            update(a, b, x, (k<<1)+1, l, (l+r)>>1);
            update(a, b, x, (k<<1)+2, (l+r)>>1, r);
            node[k] = std::min(node[(k<<1)+1], node[(k<<1)+2]);
        }
    }
    void add(int a, long long x){
        add(a, a+1, x);
    }
    void add(int a, int b, long long x, int k=0, int l=0, int r=-1){
        if(a >= b) return;
        if(r == -1) r = N;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b){
            lazy[k] += x;
            eval(k, l, r);
        }
        else{
            add(a, b, x, (k<<1)+1, l, (l+r)>>1);
            add(a, b, x, (k<<1)+2, (l+r)>>1, r);
            node[k] = std::min(node[(k<<1)+1], node[(k<<1)+2]);
        }
    }
    long long min(int a, int b, int k=0, int l=0, int r=-1){
        if(a >= b) return 9223372036854775807LL;
        if(r == -1) r = N;
        if(b <= l || r <= a) return 9223372036854775807LL;
        eval(k, l, r);
        if(a <= l && r <= b) return node[k];
        return std::min(min(a, b, (k<<1)+1, l, (l+r)>>1), min(a, b, (k<<1)+2, (l+r)>>1, r));
    }
    long long m;
    int find(int a, int b, int k=0, int l=0, int r=-1){
        if(r == -1){
            m = min(a, b);
            r = N;
        }
        if(r <= a || b <= l) return INT_MAX;
        if(r-l == 1){
            if(node[k] == m) return l;
            else return INT_MAX;
        }
        if(a <= l && r <= b){
            int valueL = min(a, b, (k<<1)+1, l, (l+r)/2);
            int valueR = min(a, b, (k<<1)+2, (l+r)/2, r);
            if(valueL == m) return find(a, b, (k<<1)+1, l, (l+r)>>1);
            if(valueR == m) return find(a, b, (k<<1)+2, (l+r)>>1, r);
            return INT_MAX;
        }
        return std::min(find(a, b, (k<<1)+1, l, (l+r)>>1), find(a, b, (k<<1)+2, (l+r)>>1, r));
    }
};

int N, Q;
int a[100000], b[100000], c[100000], d[100000];
vector<int> color[100000];
vector<int> e[100000];

int pre[100000], pos[100000];
int cnt = 0;
RSQ depth, depth2;
RMinQ EulerTour;
int et[100000];
int cnt2 = 0;
void dfs(int n, int dep, int p){
    pre[n] = cnt; cnt++;
    depth.update(pre[n], dep);
    EulerTour.update(cnt2, pre[n]); et[n] = cnt2;  cnt2++;
    rep(i, e[n].size()){
        int j = e[n][i];
        if(a[j]+b[j]-n == p) continue;
        dfs(a[j]+b[j]-n, dep+d[j], n);
        EulerTour.update(cnt2, pre[n]); cnt2++;
    }
    pos[n] = cnt;
}

int x[100000], y[100000], u[100000], v[100000];
vector<int> query[100000];
int ans[100000];

signed main(){
    cin >> N >> Q;
    rep(i, N-1){
        cin >> a[i] >> b[i] >> c[i] >> d[i];
        a[i]--; b[i]--; c[i]--;
        color[c[i]].pb(i);
        e[a[i]].pb(i);
        e[b[i]].pb(i);
    }
    depth.init(N, 0);
    depth2.init(N, 0);
    EulerTour.init(2*N);
    dfs(0, 0, -1);

    rep(i, Q){
        cin >> x[i] >> y[i] >> u[i] >> v[i];
        x[i]--; u[i]--; v[i]--;
        query[x[i]].pb(i);
    }

    rep(i, N){
        rep(j, color[i].size()){
            int k = color[i][j];
            if(pre[a[k]] > pre[b[k]]) swap(a[k], b[k]);
            depth.add(pre[b[k]], pos[b[k]], -d[k]);
            depth2.add(pre[b[k]], pos[b[k]], 1);
        }
        /*rep(j, N) cout << depth.sum(j, j+1) << " ";
        cout << endl;
        rep(j, N) cout << depth2.sum(j, j+1) << " ";
        cout << endl;*/
        rep(j, query[i].size()){
            int k = query[i][j];
            if(et[u[k]] > et[v[k]]) swap(u[k], v[k]);
            int l = EulerTour.min(et[u[k]], et[v[k]]+1);
            ans[k] = depth.sum(pre[u[k]], pre[u[k]]+1) + depth.sum(pre[v[k]], pre[v[k]]+1) - 2*depth.sum(l, l+1);
            int tmp = depth2.sum(pre[u[k]], pre[u[k]]+1) + depth2.sum(pre[v[k]], pre[v[k]]+1) - 2*depth2.sum(l, l+1);
            ans[k] += tmp * y[k];
        }
        rep(j, color[i].size()){
            int k = color[i][j];
            depth.add(pre[b[k]], pos[b[k]], d[k]);
            depth2.add(pre[b[k]], pos[b[k]], -1);
        }
    }

    rep(i, Q) cout << ans[i] << endl;
}

Measured memory_bytes: 48140