#include <bits/stdc++.h>

using namespace std;

#define loop(i, n) for(int i = 0;i < int(n);i++)
#define rloop(i, n) for(int i = int(n);i >= 0;i--)
#define range(i, a, b) for(int i = int(a);i <= int(b);i++)
#define SZ(c) int(c.size())
#define ALL(c) c.begin(), c.end()
#define RALL(c) c.rbegin(), c.rend()
#define PI acos(-1)
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
#define sfi1(v) scanf("%d",&v)
#define sfi2(v1, v2) scanf("%d %d",&v1,&v2)
#define sfi3(v1, v2, v3) scanf("%d %d %d",&v1,&v2,&v3)
#define sfll1(v) scanf("%I64d",&v);
#define sfll2(v1, v2) scanf("%I64d %I64d",&v1,&v2)
#define sfll3(v1, v2, v3) scanf("%I64d %I64d %I64d",&v1,&v2,&v3)
#define endl '\n'

typedef vector<int> vi;
typedef vector<pair<int, int> > vii;
typedef long long ll;
typedef pair<int, int> pii;

struct edge {
    int u, v, col, cost;

    bool operator<(const edge &other) const {
        return cost > other.cost;
    }
};


const int N = 1e5 + 5;
vector<edge> edges;
vector<edge> queries;
vector<int> AdjList[N];
vector<int> queryList[N];
bool cut[N];
int subTreeSize[N];
ll ans[N];
int cnt[N];
ll sum[N];
int c[N], b[N], vis[N], visid;
int n, q;


int dfs(int u, int par) {
    subTreeSize[u] = 1;
    for (int e : AdjList[u]) {
        int v = edges[e].u + edges[e].v - u;
        if (v != par && !cut[v])
            subTreeSize[u] += dfs(v, u);
    }
    return subTreeSize[u];
}

int pick(int u, int par, int size) {
    int mx = 0;
    for (int e : AdjList[u]) {
        int v = edges[e].u + edges[e].v - u;
        if (v != par && !cut[v])
            mx = max(mx, subTreeSize[v]);
    }

    if (mx <= size / 2)
        return u;
    for (int e : AdjList[u]) {
        int v = edges[e].u + edges[e].v - u;
        if (!cut[v] && v != par && subTreeSize[v] == mx) {
            return pick(v, u, size);
        }
    }

}

int getCenter(int u) {
    return pick(u, -1, dfs(u, -1));
}

void answer(int u, int par, ll w) {
    for (int id : queryList[u]) {
        if (vis[id] == visid && c[id] == 2) {
            ans[id] += w;
            ans[id] -= sum[queries[id].col];
            ans[id] += 1LL * cnt[queries[id].col] * queries[id].cost;
        }
    }

    for (int e : AdjList[u]) {
        int nxt = edges[e].u + edges[e].v - u;
        if (nxt == par || cut[nxt])continue;
        sum[edges[e].col] += edges[e].cost;
        cnt[edges[e].col]++;
        answer(nxt, u, w + edges[e].cost);
        sum[edges[e].col] -= edges[e].cost;
        cnt[edges[e].col]--;
    }
}

void visquery(int u, int par, int branch) {

    for (int id : queryList[u]) {
        if (vis[id] != visid) {
            vis[id] = visid;
            c[id] = 1;
            b[id] = branch;
        } else {
            if (b[id] == branch) {
                c[id] = 0;
            } else {
                c[id]++;
            }
        }
    }


    for (int e : AdjList[u]) {
        int nxt = edges[e].u + edges[e].v - u;
        if (nxt == par || cut[nxt])continue;
        visquery(nxt, u, branch);
    }
}

void solve(int u) {
    visid++;
    for (int id : queryList[u]) {
        vis[id] = visid;
        c[id] = 1;
        b[id] = -1;
    }

    for (int e : AdjList[u]) {
        int nxt = edges[e].u + edges[e].v - u;
        if (cut[nxt])continue;
        visquery(nxt, u, nxt);
    }

    for (int e : AdjList[u]) {
        int nxt = edges[e].u + edges[e].v - u;
        if (cut[nxt])continue;
        sum[edges[e].col] += edges[e].cost;
        cnt[edges[e].col]++;
        answer(nxt, u, edges[e].cost);
        sum[edges[e].col] -= edges[e].cost;
        cnt[edges[e].col]--;
    }
}

void centroid(int u) {
    int center = getCenter(u);
    solve(center);
    cut[center] = 1;
    for (int e : AdjList[center]) {
        int v = edges[e].u + edges[e].v - center;
        if (!cut[v])
            centroid(v);
    }
}


int main() {

#ifndef ONLINE_JUDGE
//    freopen("in.in", "r", stdin);
    //freopen("out.in", "w", stdout);
#endif
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int a, b, c, d;
    cin >> n >> q;
    loop(i, n - 1) {
        cin >> a >> b >> c >> d;
        edges.push_back({a, b, c, d});
        AdjList[a].push_back(i);
        AdjList[b].push_back(i);
    }

    loop(i, q) {
        cin >> c >> d >> a >> b;
        queries.push_back({a, b, c, d});
        queryList[a].push_back(i);
        queryList[b].push_back(i);
    }

    centroid(1);

    loop(i, q)cout << ans[i] << endl;

    return 0;
}


Measured memory_bytes: 22256