#include<iostream>
#define _USE_MATH_DEFINES
#include<math.h>
#include<vector>
#include<array>
#include<algorithm>
#include<numeric>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<ll> vec;
typedef vector<vector<ll>> mat;
typedef pair<ll,ll> P;
typedef map<ll,ll> MP;
typedef priority_queue<ll> PQ;
typedef stack<ll> ST;
typedef queue<ll> QUE;
#define pb push_back
#define st first
#define nd second
#define SZ(x) ((int)(x).size())
#define FOR(i,s,n) for(int i=(int)(s); i< (int)(n); i++)
#define rep(i,n) FOR(i,0,n)
#define all(x) (x).begin(),(x).end()
#define each(x,c) for(auto x: (c))
#define LB(x,a) lower_bound(all(x), a)
#define UB(x,a) upper_bound(all(x), a)
const ll mod=1e9+7;
const ll INF=1e18;
const double EPS=1.0e-10;
const double PI=M_PI;

class lca {
public:
    const int n = 0;
    const int log2_n = 0;
    mat parent;
    vec depth;

    lca() {}

    lca(const mat &g, int root)
        : n(g.size()), log2_n(log2(n) + 1), parent(log2_n, vec(n)), depth(n) {
        dfs(g, root, -1, 0);
        for (int k = 0; k + 1 < log2_n; k++) {
            for (int v = 0; v < (int)g.size(); v++) {
                if (parent[k][v] < 0)
                    parent[k + 1][v] = -1;
                else
                    parent[k + 1][v] = parent[k][parent[k][v]];
            }
        }
    }

    void dfs(const mat &g, int v, int p, int d) {
        parent[0][v] = p;
        depth[v] = d;
        for (auto &e : g[v]) {
            if (e != p) dfs(g, e, v, d + 1);
        }
    }

    int get(int u, int v) {
        if (depth[u] > depth[v]) swap(u, v);
        for (int k = 0; k < log2_n; k++) {
            if ((depth[v] - depth[u]) >> k & 1) {
                v = parent[k][v];
            }
        }
        if (u == v) return u;
        for (int k = log2_n - 1; k >= 0; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }
};

struct edge{int to,color,cost;};
vec d(100010),num(100010,0),len(100010,0);
vector<map<int,P>> mp(100010);
vector<vector<edge>> G(100010);
vector<set<int>> query(100010);
void DFS(int s, int p){
    each(e,G[s]){
        if(e.to==p) continue;
        d[e.to]=d[s]+e.cost;
        num[e.color]++;
        len[e.color]+=e.cost;
        DFS(e.to,s);
        num[e.color]--;
        len[e.color]-=e.cost;
    }
    for(auto itr=query[s].begin(); itr!=query[s].end(); itr++){
        mp[s][*itr]={num[*itr],len[*itr]};
    }
    return;
}

int main(){
    int N,Q; cin>>N>>Q;
    mat g(N+1);
    rep(i,N-1){
        int a,b,c,d; scanf("%d %d %d %d",&a,&b,&c,&d);
        G[a].pb({b,c,d}); G[b].pb({a,c,d});
        g[a].pb(b), g[b].pb(a);
    }
    lca LCA(g,1);
    vec x(Q),y(Q),u(Q),v(Q),p(Q);
    rep(i,Q){
        scanf("%lld %lld %lld %lld",&x[i],&y[i],&u[i],&v[i]);
        p[i]=LCA.get(u[i],v[i]);
        query[u[i]].insert(x[i]);
        query[v[i]].insert(x[i]);
        query[p[i]].insert(x[i]);
    }
    d[1]=0; DFS(1,0);
    rep(i,Q){
        ll D=d[u[i]]+d[v[i]]-2*d[p[i]]+y[i]*(mp[u[i]][x[i]].st+mp[v[i]][x[i]].st-2*mp[p[i]][x[i]].st)
             -(mp[u[i]][x[i]].nd+mp[v[i]][x[i]].nd-2*mp[p[i]][x[i]].nd);
        printf("%lld\n",D);
    }
    return 0;
}

Measured memory_bytes: 70816