#include <bits/stdc++.h>
#define For(i, a, b) for(int (i)=(a); (i)<(b); ++(i))
#define rFor(i, a, b) for(int (i)=(a)-1; (i)>=(b); --(i))
#define rep(i, n) For((i), 0, (n))
#define rrep(i, n) rFor((i), (n), 0)
#define fi first
#define se second
using namespace std;
typedef long long lint;
typedef pair<int, int> pii;
typedef complex<double> xy_t;
const lint mod = 1e9 + 7;
const int MAX = 100010;

typedef struct edge{
    int to, col;
    lint dist;
    edge(int t, int c, lint d){
        to = t; col = c; dist = d;
    }
}edge;

typedef struct Segtree{
    int n = 1;
    vector<int> node;
    vector<int> depth;
    
    Segtree(int n_, vector<int> d){
        while(n < n_) n *= 2;
        node.resize(2*n-1, n-1);
        depth.resize(n, MAX);
        rep(i, d.size()) depth[i] = d[i];
    }
    
    void update(int i, int x){
        i += n-1;
        node[i] = x;
        while(i){
            i = (i-1) / 2;
            if(depth[node[2*i+1]] < depth[node[2*i+2]]) node[i] = node[2*i+1];
            else node[i] = node[2*i+2];
        }
    }
    
    int getmin(int a, int b, int i, int l, int r){
        if(r<=a || b<=l) return n-1;
        if(a<=l && r<=b) return node[i];
        int lid = getmin(a, b, 2*i+1, l, (l+r)/2);
        int rid = getmin(a, b, 2*i+2, (l+r)/2, r);
        if(depth[lid] < depth[rid]) return lid;
        else return rid;
    }
}Segtree;

int n, q;
int u[MAX], v[MAX], lca[MAX];
int x[MAX];
lint y[MAX];
map<pii, lint> col_num, col_dist;
lint dv[MAX];
vector<edge> G[MAX];
lint now_col[MAX], now_dist[MAX];
vector<int> used_col[MAX];

void lca_dfs(int nowv, int prev, int &cur, int dep, vector<int> &id, vector<int> &vs, vector<int> &depth){
    if(id[nowv] < 0) id[nowv] = cur;
    vs.push_back(nowv);
    depth.push_back(dep);
    ++cur;
    for(edge &e: G[nowv])if(e.to != prev){
        lca_dfs(e.to, nowv, cur, dep+1, id, vs, depth);
        vs.push_back(nowv);
        depth.push_back(dep);
        ++cur;
    }
}

void getlca(){
    vector<int> id(n, -1);
    vector<int> vs, depth;
    int cur = 0;
    lca_dfs(0, -1, cur, 0, id, vs, depth);
    Segtree st(2*MAX, depth);
    rep(i, depth.size()) st.update(i, i);
    rep(i, q){
        lca[i] = vs[st.getmin(min(id[u[i]], id[v[i]]), max(id[u[i]], id[v[i]]) + 1, 0, 0, st.n)];
    }
}

void dfs(int nowv, lint nowd){
    dv[nowv] = nowd;
    for(int tc: used_col[nowv]){
        col_num[pii(nowv, tc)] = now_col[tc];
        col_dist[pii(nowv, tc)] = now_dist[tc];
    }
    for(edge &e: G[nowv])if(dv[e.to] < 0){
        ++now_col[e.col];
        now_dist[e.col] += e.dist;
        dfs(e.to, nowd + e.dist);
        --now_col[e.col];
        now_dist[e.col] -= e.dist;
    }
}

int main(){
    scanf("%d%d", &n, &q);
    rep(i, n-1){
        int a, b, c;
        lint d;
        scanf("%d%d%d%lld", &a, &b, &c, &d);
        G[--a].emplace_back(--b, --c, d);
        G[b].emplace_back(a, c, d);
    }
    rep(i, q){
        scanf("%d%lld%d%d", &x[i], &y[i], &u[i], &v[i]);
        --x[i]; --u[i]; --v[i];
    }
    getlca();
    rep(i, q){
        used_col[u[i]].push_back(x[i]);
        used_col[v[i]].push_back(x[i]);
        used_col[lca[i]].push_back(x[i]);
    }
    rep(i, n){
        dv[i] = -1;
        now_col[i] = now_dist[i] = 0;
    }
    dfs(0, 0);
    rep(i, q){
        lint d_u = dv[u[i]] - col_dist[pii(u[i], x[i])] + col_num[pii(u[i], x[i])] * y[i];
        lint d_v = dv[v[i]] - col_dist[pii(v[i], x[i])] + col_num[pii(v[i], x[i])] * y[i];
        lint d_lca = dv[lca[i]] - col_dist[pii(lca[i], x[i])] + col_num[pii(lca[i], x[i])] * y[i];
        printf("%lld\n", d_u + d_v - 2*d_lca);
    }
}

Measured memory_bytes: 52200