#pragma GCC optimize("Ofast")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,popcnt,abm,mmx,tune=native")
#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stdio.h>
#include <cstdio>
#include <math.h>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <deque>
#include <random>
#include <iomanip>
#include <bitset>
 
using namespace std;
 
template<typename T> void uin(T &a, T b) {
    if (b < a) {
        a = b;
    }
}
 
template<typename T> void uax(T &a, T b) {
    if (b > a) {
        a = b;
    }
}
 
#define left left228
#define right right228
#define prev prev228
#define mp make_pair
#define all(v) v.begin(), v.end()
#define forn(i, n) for (int i = 0; i < (int)n; ++i)
#define firn(i, n) for (int i = 1; i < (int)n; ++i)
#define x first
#define y second

const int N = 100 * 1000 + 228, LG = 20;

struct Edge
{
    int u, v, c, l;
    Edge() {}
    Edge(int _u, int _v, int _c, int _l) {
        u = _u, v = _v, c = _c, l = _l;
    }
};
vector< Edge > edges;
int n, q;
vector< pair<int,int> > g[N];
vector<int> numbers[N], qq[N];
int p[N][LG], h[N], tin[N], tout[N], timer = 0;

void dfs(int v, int par = 1, int H = 0) {
    h[v] = H;
    p[v][0] = par;
    for (int k = 1; k < LG; ++k) {
        p[v][k] = p[p[v][k - 1]][k - 1];
    }
    tin[v] = ++timer;
    for (pair<int,int>go: g[v]) {
        int to = go.first;
        if (to != par) dfs(to, v, H + go.second);
    }
    tout[v] = timer;
}
bool anc(int u, int v) {
    return tin[u] <= tin[v] && tout[u] >= tout[v];
}
int get_lca(int u, int v) {
    if (anc(u, v)) return u;
    if (anc(v, u)) return v;
    for (int k = LG - 1; k + 1; --k) {
        if (!anc(p[u][k], v)) u = p[u][k];
    }
    return p[u][0];
}
int get_dist(int u, int v) {
    return h[u] + h[v] - 2 * h[get_lca(u,v)];
}
pair<int, int> t[N];
void incCnt(int i, int x) {
    --i;
    for (; i < n; i |= (i + 1)) {
        t[i].first += x;
    }
}
void incSum(int i, int x) {
    --i;
    for (; i < n; i |= (i + 1)) {
        t[i].second += x;
    }
}
void addCnt(int l, int r, int x) {
    incCnt(l, x);
    incCnt(r + 1, -x);
}
void addSum(int l, int r, int x) {
    incSum(l, x);
    incSum(r + 1, -x);
}
int gg = 0;
int getCnt(int i) {
    --i;
    gg = 0;
    for (; i >= 0; i = (i & (i + 1)) - 1) {
        gg += t[i].first;
    }
    return gg;
}
int getSum(int i) {
    --i;
    gg = 0;
    for (; i >= 0; i = (i & (i + 1)) - 1) {
        gg += t[i].second;
    }
    return gg;
}

int ans[N];
int X[N], Y[N], U[N], V[N];

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> q;
    for (int i = 0; i < n - 1; ++i) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        g[a].emplace_back(b, d);
        g[b].emplace_back(a, d);
        edges.emplace_back(a, b, c, d);
        numbers[c].emplace_back(i);
    }
    dfs(1);
    for (int i = 0; i < q; ++i) {
        cin >> X[i] >> Y[i] >> U[i] >> V[i];
        qq[X[i]].emplace_back(i);
    }
    for (int color = 1; color < n; ++color) {
        for (int i : numbers[color]) {
            int u = edges[i].u, v = edges[i].v, l = edges[i].l;
            if (anc(u, v)) swap(u, v);
            // v = p[u] u --> v
            addCnt(tin[u], tout[u], 1);
            addSum(tin[u], tout[u], l);
        }
        for (int i : qq[color]) {
            int y = Y[i], u = U[i], v = V[i];
            int res = get_dist(u, v);
            int lca = get_lca(u, v);
            res += (getCnt(tin[u]) + getCnt(tin[v]) - 2 * getCnt(tin[lca])) * y;
            res -= (getSum(tin[u]) + getSum(tin[v]) - 2 * getSum(tin[lca]));
            ans[i] = res;
        }
        for (int i : numbers[color]) {
            int u = edges[i].u, v = edges[i].v, l = edges[i].l;
            if (anc(u, v)) swap(u, v);
            // v = p[u] u --> v
            addCnt(tin[u], tout[u], -1);
            addSum(tin[u], tout[u], -l);
        }
    }
    for (int i = 0; i < q; ++i) {
        cout << ans[i] << '\n';
    }
    return 0;
}
 
/*
 
 
4 2 1
1 1
2 0 2
2 1 3
1 2
 
 
5 2 1
1 1
2 0 2
2 1 3
2 2 4
1 3
 
 
 
3 3 3
2 1 2
2 0 2
1 0
 
3 1 3 6
3 0 2 3
2 1 3
4 0 1 2 12
2 5 6
4 4 6 13 14
4 0 4 5 13
3 8 9 15
2 7 9
2 7 8
2 11 12
2 10 12
3 3 10 11
4 5 6 14 15
3 5 13 15
3 7 13 14
 
*/

Measured memory_bytes: 30064