#include "bits/stdc++.h"
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using vvl = vector<vl>;
const ll INF = 1LL << 60;
const ll MOD = 1000000007;
template <class T>
bool chmax(T &a, const T &b) {
    return (a < b) ? (a = b, 1) : 0;
}
template <class T>
bool chmin(T &a, const T &b) {
    return (b < a) ? (a = b, 1) : 0;
}

// 0-indexed bottom up Segment Tree
// UNIT is the identity element of operation func
template <typename T = int>
struct SegmentTree {
    using F = function<T(T, T)>;
    int n;
    vector<T> dat;
    F func;
    T UNIT;

    SegmentTree(int n_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
        n = 1;
        // full binary tree: num of leaves = n = 2^k >= n_
        while (n < n_)
            n *= 2;
        dat.assign(2 * n - 1, UNIT);
    }
    SegmentTree(vector<T> v_, F func_, T UNIT_) : func(func_), UNIT(UNIT_) {
        n = 1;
        while (n < v_.size())
            n *= 2;
        dat.assign(2 * n - 1, UNIT);
        for (int i = 0; i < v_.size(); ++i) {
            dat[n - 1 + i] = v_[i];
        }
        for (int i = n - 2; i >= 0; --i) {
            dat[i] = func(dat[2 * i + 1], dat[2 * i + 2]);
        }
    }
    void update(int k, T a) {
        // leaves are at index n-1 to 2*n-2
        k += n - 1;
        dat[k] = a;
        while (k > 0) {
            // k -> parent node
            k = (k - 1) / 2;
            // func(child nodes)
            dat[k] = func(dat[2 * k + 1], dat[2 * k + 2]);
        }
    }
    // get result of func() in [l, r)
    T query(int l, int r) {
        l += n - 1;
        r += n - 1;
        T ret = UNIT;
        while (l < r) {
            if ((l & 1) == 0)
                ret = func(ret, dat[l]);
            if ((r & 1) == 0)
                ret = func(ret, dat[r - 1]);
            l = l / 2;
            r = (r - 1) / 2;
        }
        return ret;
    }
};

// get LCA on the tree
// constructor: n = size of the graph
// addEdge:
// build: after adding all edge, build Euler tour and seg tree
struct LCA {
    int n;
    int k;
    vector<int> depth;
    vector<int> eulerTour;
    vector<int> firstVisit;
    vector<vector<int>> edges;
    SegmentTree<pair<int, int>> segTree;
    static pair<int, int> pairComp(pair<int, int> a, pair<int, int> b) {
        if (a.first < b.first)
            return a;
        else
            return b;
    }
    LCA(int n)
        : n(n), k(0), depth(2 * n - 1), eulerTour(2 * n - 1), firstVisit(n), edges(n),
          segTree(2 * n, pairComp, make_pair(numeric_limits<int>::max(), 0)){};
    void addEdge(int from, int to) {
        edges[from].push_back(to);
        edges[to].push_back(from);
    }
    void dfs(int curr = 0, int par = -1, int d = 0) {
        firstVisit[curr] = k;
        eulerTour[k] = curr;
        depth[k++] = d;
        for (auto &e : edges[curr]) {
            if (e != par) {
                dfs(e, curr, d + 1);
                eulerTour[k] = curr;
                depth[k++] = d;
            }
        }
    }
    void build(int root = 0) {
        dfs(root);
        for (int i = 0; i < 2 * n - 1; ++i) {
            segTree.update(i, make_pair(depth[i], eulerTour[i]));
        }
    }
    // return LCA node of l and r
    int operator()(int l, int r) {
        int left = firstVisit[l];
        int right = firstVisit[r];
        if (left > right)
            swap(left, right);
        return segTree.query(left, right + 1).second;
    }
    int getDepth(int k) { return depth[firstVisit[k]]; }
};
vi ret(100001);
vector<pii> dist(100001);
vector<vector<tuple<int, int, int, int>>> queries(100001);
vector<vector<tuple<int, int, int>>> edges(100001);

void dfs(int curr, int par) {
    for (auto &q : queries[curr]) {
        int d = dist[100000].first;
        d -= dist[get<1>(q)].first;
        d += dist[get<1>(q)].second * get<2>(q);
        d *= get<0>(q);
        ret[get<3>(q)] += d;
    }
    for (auto &e : edges[curr]) {
        int next = get<0>(e);
        int color = get<1>(e);
        int d = get<2>(e);
        if (next != par) {
            dist[100000].first += d;
            dist[color].first += d;
            dist[color].second++;
            dfs(get<0>(e), curr);
            dist[100000].first -= d;
            dist[color].first -= d;
            dist[color].second--;
        }
    }
}

int main() {
    int n, q;
    cin >> n >> q;
    vi a(n - 1), b(n - 1), c(n - 1), d(n - 1);
    for (int i = 0; i < n - 1; ++i) {
        cin >> a[i] >> b[i] >> c[i] >> d[i];
        a[i]--;
        b[i]--;
        edges[a[i]].emplace_back(b[i], c[i], d[i]);
        edges[b[i]].emplace_back(a[i], c[i], d[i]);
    }
    LCA lca(n);
    for (int i = 0; i < n - 1; ++i) {
        lca.addEdge(a[i], b[i]);
    }
    lca.build();
    vi x(q), y(q), u(q), v(q);
    for (int i = 0; i < q; ++i) {
        cin >> x[i] >> y[i] >> u[i] >> v[i];
        u[i]--;
        v[i]--;
    }
    for (int i = 0; i < q; ++i) {
        int thisLCA = lca(u[i], v[i]);
        queries[u[i]].emplace_back(1, x[i], y[i], i);
        queries[v[i]].emplace_back(1, x[i], y[i], i);
        queries[thisLCA].emplace_back(-2, x[i], y[i], i);
    }
    dfs(0, -1);
    for (int i = 0; i < q; ++i) {
        cout << ret[i] << "\n";
    }

    return 0;
}

Measured memory_bytes: 36340