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

// macros
#define overload_rep(_1, _2 ,_3 ,name, ...) name
#define re_p(i, n) for(int i = 0; i < (n); ++i)
#define r_ep(i, x, y) for(int i = (x); i < (y); ++i)
#define rep(...) overload_rep(__VA_ARGS__, r_ep, re_p)(__VA_ARGS__)
#define all(a) a.begin(), a.end()
#ifndef STOP_DEBUG
#define debug(...)\
    do { cerr << boolalpha << "[" << #__VA_ARGS__ << "]:";\
    debug_cerr(__VA_ARGS__); cerr << noboolalpha; } while (0)
#else
#define debug(...)
#endif

// functions
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
void debug_cerr(){ cerr << '\n'; }
template<class Head, class... Tail>
void debug_cerr(Head head, Tail... tail){
    cerr << ' ' << head;
    debug_cerr(tail...);
}

// cin/cout setup
struct IoSetup{
    IoSetup(){
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << setprecision(20);
    }
} iosetup;

// SOLVE

struct edge{
    int to, color, cost;
    edge(int to = 0, int color = 0, int cost = 0) : to(to), color(color), cost(cost) {}
};

struct memo{
    int cnt, dist;
    memo(int cnt = 0, int dist = 0) : cnt(cnt), dist(dist) {}
};

struct query{
    int id, color, ndist, coeff;
    query(int id = 0, int color = 0, int ndist = 0, int coeff = 0) : id(id), color(color), ndist(ndist), coeff(coeff) {}
};

int N, Q;
int parent[100000][20];
int dist[100000];
int depth[100000];
int ans[100000];
memo memos[100000];
vector<edge> graph[100000];
vector<query> queries[100000];

void init_dfs(int v, int p, int c, int d){
    parent[v][0] = p;
    dist[v] = c;
    depth[v] = d;
    for(edge e : graph[v])if(e.to != p){
        init_dfs(e.to, v, c + e.cost, d + 1);
    }
}

void init_lca(int root){
    init_dfs(root, root, 0, 0);
    rep(j, 19)rep(i, N){
        parent[i][j + 1] = parent[parent[i][j]][j];
    }
}

int lca(int x, int y){
    if(depth[x] > depth[y])swap(x, y);
    int depdif = depth[y] - depth[x];
    rep(i, 20){
        if(depdif & (1 << i)){
            y = parent[y][i];
        }
    }
    if(x == y)return x;
    for(int i = 19; i >= 0; i--){
        if(parent[x][i] != parent[y][i]){
            x = parent[x][i];
            y = parent[y][i];
        }
    }
    return parent[x][0];
}

void query_dfs(int v, int p){
    for(query q : queries[v]){
        memo tmp = memos[q.color];
        ans[q.id] += q.coeff * (tmp.cnt * q.ndist - tmp.dist);
    }
    for(edge e : graph[v])if(e.to != p){
        memos[e.color].cnt++;
        memos[e.color].dist += e.cost;
        query_dfs(e.to, v);
        memos[e.color].cnt--;
        memos[e.color].dist -= e.cost;
    }
}

int main(){

    cin >> N >> Q;
    rep(i, N - 1){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--; b--; c--;
        graph[a].push_back(edge(b, c, d));
        graph[b].push_back(edge(a, c, d));
    }

    init_lca(0);

    rep(i, Q){
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        x--; u--; v--;
        int t = lca(u, v);
        ans[i] += dist[u] + dist[v] - 2 * dist[t];
        queries[u].push_back(query(i, x, y, 1));
        queries[v].push_back(query(i, x, y, 1));
        queries[t].push_back(query(i, x, y, -2));
    }

    query_dfs(0, -1);
    rep(i, Q)cout << ans[i] << '\n';
    return 0;

}

Measured memory_bytes: 30196