#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;


constexpr ll MOD = 1000000007;

struct lowest_common_ancestor_log {
    int L, N;
    vi depth, link;

    lowest_common_ancestor_log() { }

    lowest_common_ancestor_log(const vvi &graph, int root = 0) : N(graph.size()) {
        L = 32 - __builtin_clz(N);
        depth.resize(N);
        link.resize(L*N);
        init(root, root, graph);
    }

    /*
     * Initializes the link table in O(NlogN). link[l * N + i] contains the index
     * of the (2 ** l)th ancestor of vertex i.
     */
    void init(int loc, int par, const vvi &graph) {
        link[loc] = par;
        for (int l = 1; l < L; l++)
            link[l*N + loc] = link[(l-1)*N + link[(l-1)*N + loc]];

        for (int nbr : graph[loc]) if (nbr != par) {
            depth[nbr] = depth[loc] + 1;
            init(nbr, loc, graph);
        }
    }

    // Returns the index of the dist-th ancestor of vertex loc in O(logN).
    int above(int loc, int dist) {
        dist = min(dist, N - 1);
        for (int l = 0; l < L; l++)
            if (dist & (1 << l))
                loc = link[l*N + loc];
        return loc;
    }

    // Returns the least common ancestor of vertices u and v in O(logN).
    int lca(int u, int v) {
        if (depth[u] > depth[v]) swap(u, v);
        v = above(v, depth[v] - depth[u]);
        if (u == v) return u;

        for (int l = L - 1; l >= 0; l--) {
            if (link[l*N + u] != link[l*N + v])
                u = link[l*N + u], v = link[l*N + v];
        }
        return link[u];
    }

    int dist(int u, int v) {
        return depth[u] + depth[v] - 2 * depth[lca(u, v)];
    }

    bool on_path(int u, int v, int inx) {
        return dist(u, v) == dist(u, inx) + dist(inx, v);
    }
};

constexpr int HEAVY_THRESHOLD = 300;

vll get_dists(vi& parent, vll& lengths, vi& colors, vi& preorder, int color, bool use_dists) {
    int N = parent.size();
    vll dists(N, 0);
    for (int i=1; i<N;i++) {
        int v = preorder[i];
        if (color == -1 || colors[v] == color) {
            if (use_dists) {
                dists[v] = dists[parent[v]] + lengths[v];
            } else {
                dists[v] = dists[parent[v]] + 1;
            }
        } else {
            dists[v] = dists[parent[v]];
        }
    }

    return dists;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int N, Q;
    cin >> N >> Q;

    vvi adj(N);
    map<pair<int, int>, int> cmap;
    map<pair<int, int>, ll> dmap;
    vi num_color(N, 0);


    for(int i=0; i < N-1; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--; b--; c--;

        adj[a].push_back(b);
        adj[b].push_back(a);

        cmap[{a, b}] = c;
        cmap[{b, a}] = c;
        num_color[c]++;

        dmap[{a, b}] = d;
        dmap[{b, a}] = d;
    }

    lowest_common_ancestor_log lca(adj);

    vi parent(N, -1);
    vll lengths(N, 0);
    vi colors(N, -1);
    vvi color_lists(N);

    vi preorder;
    queue<int> bfs;
    bfs.push(0);
    parent[0] = 0;

    while (!bfs.empty()) {
        int v = bfs.front();
        bfs.pop();

        preorder.push_back(v);

        for (int w : adj[v]) {
            if (parent[w] == -1) {
                parent[w] = v;
                lengths[w] = dmap[{v, w}];
                colors[w] = cmap[{v, w}];
                color_lists[colors[w]].push_back(w);
                bfs.push(w);
            }
        }
    }

    vll all_dists = get_dists(parent, lengths, colors, preorder, -1, true);

    vvll heavy_dists(N);
    vvll heavy_edges(N);
    
    for (int c=0; c<N; c++) {
        if (num_color[c] >= HEAVY_THRESHOLD) {
            heavy_dists[c] = get_dists(parent, lengths, colors, preorder, c, true);
            heavy_edges[c] = get_dists(parent, lengths, colors, preorder, c, false);
        }
    }


    for (int q=0; q < Q; q++) {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        x--; u--; v--;

        int g = lca.lca(u, v);

        ll ans = all_dists[u] + all_dists[v] - 2*all_dists[g];

        if (num_color[x] >= HEAVY_THRESHOLD) {
            // heavy
            ans -= heavy_dists[x][u] + heavy_dists[x][v] - 2*heavy_dists[x][g];
            ans += y * (heavy_edges[x][u] + heavy_edges[x][v] - 2*heavy_edges[x][g]);
        } else {
            // light
            for (int w : color_lists[x]) {
                if (w == lca.lca(u, w)) {
                    ans += y - lengths[w];
                }
                if (w == lca.lca(v, w)) {
                    ans += y - lengths[w];
                }
                if (w == lca.lca(g, w)) {
                    ans -= 2*(y - lengths[w]);
                }
            }
        }

        cout << ans << endl;
    }

    return 0;
}


Measured memory_bytes: 59000