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

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const ull mod = 1e9 + 7;
#define REP(i,n) for(int i=0;i<(int)n;++i)

//debug
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;

template<class S, class T> ostream& operator << (ostream& os, const pair<S, T> v){
  os << "(" << v.first << ", " << v.second << ")"; return os;
}
template<class T> ostream& operator << (ostream& os, const vector<T> v){
  for(int i = 0; i < v.size(); i++){if(i > 0){os << " ";} os << v[i];} return os;
}
template<class T> ostream& operator << (ostream& os, const vector<vector<T>> v){
  for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}

// RMQ

typedef ll Val;
typedef pair<Val, Val> pVV;
const Val INF_Val = LLONG_MAX;
const int ME = 18;
const int MN = 1<<ME;
class RMQ_segtree{
public:
    pVV dat[2*MN-1];
    RMQ_segtree(){
        REP(i, 2*MN-1) dat[i] = make_pair(INF_Val, -1);
    }

    void update(int k, Val a){
        //k番目の要素をaに変更
        k += MN-1;
        dat[k] = make_pair(a, k-(MN-1));
        while(k>0){
            k = (k-1)/2;
            dat[k] = min(dat[2*k+1], dat[2*k+2]);
        }
    }

   pVV recursion(int a, int b, int k, int l, int r){
        //最小値計算用の再帰関数
        if(r<=a || b<=l) return make_pair(INF_Val, -1);
        if(a<=l && r<=b) return dat[k];
        else{
            pVV vl = recursion(a, b, 2*k+1, l, (l+r)/2);
            pVV vr = recursion(a, b, 2*k+2, (l+r)/2, r);
            return min(vl, vr);
        }
    }

    pVV minimum(int a, int b){
        //区間[a, b)の最小値
        return recursion(a, b, 0, 0, MN);
    }

    void print_val(int a, int b){
        //区間[a, b)の値を出力
        for(int i=a;i<b;i++) cout << dat[i+MN-1].first << endl;
        cout << endl;
    }
};

// LCA

const ll MAX_N = 101010;

vector<ll> G[MAX_N];
ll vs[2*MAX_N-1];
ll depth[2*MAX_N-1];
ll id[MAX_N];
RMQ_segtree rmq;

void dfs(ll now, ll par, ll d, ll &k){
    id[now] = k;
    vs[k] = now;
    depth[k] = d;
    k++;
    REP(i, G[now].size()){
        ll next = G[now][i];
        if(next == par) continue;
        dfs(next, now, d+1, k);
        vs[k] = now;
        depth[k] = d;
        k++;
    }
}

void init(ll N){
    ll k = 0;
    dfs(0, -1, 0, k);
    REP(i, 2*N-1) rmq.update(i, depth[i]); 
}

ll lca(ll u, ll v){
    ll mi = min(id[u], id[v]);
    ll ma = max(id[u], id[v]);
    return vs[rmq.minimum(mi, ma+1).second];
}

struct edge{
    ll to, col, len;
};

struct query{
    ll query_id, id, col, y;
};

vector<edge> T[MAX_N];
vector<query> Qs[MAX_N];
ll cd[3][MAX_N];
ll num_col[MAX_N];
ll dist_col[MAX_N];
ll N, Q;

void dfs_colorful(ll now, ll par, ll dist){
    REP(i, Qs[now].size()){
        query q = Qs[now][i];
        cd[q.id][q.query_id] = dist - dist_col[q.col] + q.y * num_col[q.col];
    }

    ll to_par_col, to_par_len;
    REP(i, T[now].size()){
        edge e = T[now][i];
        if(e.to == par){
            to_par_col = e.col;
            to_par_len = e.len;
            continue;
        }
        num_col[e.col]++;
        dist_col[e.col] += e.len;
        dfs_colorful(e.to, now, dist+e.len);
    }
    if(now != 0){
        num_col[to_par_col]--;
        dist_col[to_par_col] -= to_par_len;
    }
    return;
}



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

    cin >> N >> Q;

    REP(i, MAX_N) num_col[i] = 0;
    REP(i, MAX_N) dist_col[i] = 0;

    REP(i, N-1){
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        a--, b--;
        edge e = {b, c, d};
        edge f = {a, c, d};
        G[a].push_back(b);
        G[b].push_back(a);
        T[a].push_back(e);
        T[b].push_back(f);
    }

    init(N);

    REP(q, Q){
        ll x, y, u, v;
        cin >> x >> y >> u >> v;
        u--, v--;
        ll w = lca(u, v);
        query tmp1 = {q, 0, x, y};
        query tmp2 = {q, 1, x, y};
        query tmp3 = {q, 2, x, y};
        Qs[u].push_back(tmp1);
        Qs[v].push_back(tmp2);
        Qs[w].push_back(tmp3);
    }

    dfs_colorful(0, -1, 0);

    REP(q, Q){
        cout << cd[0][q] + cd[1][q] - 2*cd[2][q] << endl;
    }

    /*
    REP(i, 3){
        REP(j, Q){
            cout << cd[i][j] << " "; 
        }
        cout << endl;
    }
    */

    return 0;
}

Measured memory_bytes: 53744