#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<vector<int>> vvi;
typedef vector<string> vs;
typedef unordered_set<int> si;
typedef pair<int, int> pp;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
#define all(e) (e).begin(), (e).end()
#define pb push_back

template <typename T>
void printV(vector<T> A) {
    if (A.empty()) cerr << "EMTPY\n";
    else { 
        cerr << "[";
        for (int i = 0; i < A.size() -1 ; ++i) {
            cerr << A[i] << ", ";
        }
        if (A.size()) cerr << A.back() << "]\n";
    }
}


template <typename T>
void printVV(vector<vector<T>> A) {
    cerr << "[";
    for (auto v : A) {
        printV<T>(v);
    }
    cerr << "]";
}

template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
    cerr << name << ": " << arg1 << endl;
}

template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ...args) {
    const char* comma = strchr(names + 1, ',');
    cerr.write(names, comma - names) << ": " << arg1 << " |";
    __f(comma + 1, args...);
}

const int LOGN = 18;
const int MAXN = 1e5 + 10;

struct QUERY {
    int id,c,v,z;
};

vi graph[MAXN], colors[MAXN], dist[MAXN];
int lca[MAXN][LOGN];
ll tin[MAXN], tout[MAXN];
ll timer;
vector<QUERY> all[MAXN];
vi ans;

ll clen[MAXN];
ll csum[MAXN];


void dfs(int node) {
    tin[node] = ++timer;
    for (int i = 0; i < graph[node].size(); ++i) {
        auto to = graph[node][i];
        if (to == lca[node][0]) continue;
        lca[to][0] = node;
        for (int L = 1; L < LOGN; ++L) {
            lca[to][L] = lca[lca[to][L-1]][L-1];
        }
        dfs(to);
    }
    tout[node] = timer;
}

bool isancestor(int u, int v) {
    return tin[u] <= tin[v] && tout[u] >= tout[v];
}

int find_lca(int u, int v) {
    if (isancestor(u,v)) return u;
    if (isancestor(v,u)) return v;
    for (int L = LOGN-1; L >= 0; --L) {
        if (!isancestor(lca[u][L], v)) u = lca[u][L];
    }
    return lca[u][0];
}

void solve(int node, ll totalSum) {
    for (auto& q: all[node]) {
        ans[q.id] = ans[q.id] + q.z * (totalSum - csum[q.c] + clen[q.c] * q.v);
    }

    for (int i= 0; i < graph[node].size(); ++i) {
        auto to = graph[node][i];
        if (to == lca[node][0]) continue;
        csum[colors[node][i]] += dist[node][i];
        ++clen[colors[node][i]];

        solve(to, totalSum + dist[node][i]);
        csum[colors[node][i]] -= dist[node][i];
        --clen[colors[node][i]];
    }
}

int main(int argc, char **argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    timer = 0;
    memset(clen, 0, sizeof(clen));
    memset(csum, 0, sizeof(csum));

    ll n, q; cin >> n >> q;
    for (int i = 0; i < n-1; ++i) {
        int a, b, c, d; cin >> a >> b >> c >> d;
        a -= 1, b -= 1;
        graph[a].pb(b);
        graph[b].pb(a);
        colors[a].pb(c);
        colors[b].pb(c);
        dist[a].pb(d);
        dist[b].pb(d);
    }
    dfs(0);
    ans = vi(q);
    for (int i=0; i < q; ++i) {
        int x, y, u, v; cin >> x >> y >> u >> v;
        u--,v--;

        int w = find_lca(u,v);
        all[u].pb({i,x,y,1});
        all[v].pb({i,x,y,1});
        all[w].pb({i,x,y,-2});
    }

    solve(0,0);
    for (int i = 0; i < q; ++i) {
        cout << ans[i] << '\n';
    }

    return 0;
}



Measured memory_bytes: 41972