#ifdef _MSC_VER
#include <__msvc_all_public_headers.hpp>
#undef min
#undef max
#else
#define NDEBUG
#include <bits/stdc++.h>
#endif

using namespace std;
using large = long long;

struct Edge {
    int dest;
    int color;
    int length;
};

struct Vertex {
    int name;
    int depth;
    Edge parent;
    vector<Edge> edges;
};

struct Query {
    int x, y, a, b;
    int qid;
    int coeff;
};

constexpr int Max = 100'000;
static int N;
static int B;

static std::vector<std::vector<Edge>> edge;
static std::vector<std::vector<int>> ancestors;
static std::vector<long long> cost;
static std::vector<int> depth;

static std::vector<long long> ans;
static std::array<std::vector<Query>, Max> queries;

static void dfs_depth(int v = 0, int d = 0, int p = -1, int c = 0) {
    if (p != -1)
        ancestors[v][0] = p;
    depth[v] = d;
    cost[v] = c;

    for (const auto& e : edge[v]) {
        if (e.dest == p)
            continue;
        dfs_depth(e.dest, d + 1, v, c + e.length);
    }
}

static void doubling() {
    for (auto i = 1; i <= B; ++i) {
        for (auto v = 0; v < N; ++v) {
            ancestors[v][i] = ancestors[ancestors[v][i - 1]][i - 1];
        }
    }
}

static void init(int n) {
    N = n;
    B = 0;
    while ((1 << B) < n)
        B++;

    ancestors.assign(n + 1, std::vector<int>(B + 1, n));
    depth.assign(n, -1);
    cost.assign(n, 0);

    dfs_depth();
    doubling();
}

static int lca(int a, int b) {
    if (depth[b] > depth[a])
        swap(a, b);

    // bubble `a` up to the same depth of `b`
    {
        int gap = depth[a] - depth[b];
        for (int i = B; i >= 0; --i) {
            int step = (1 << i);
            if (gap >= step) {
                gap -= step;
                a = ancestors[a][i];
            }
        }
    }

    if (a == b)
        return a;

    for (int i = B; i >= 0; --i) {
        if (ancestors[a][i] != ancestors[b][i]) {
            a = ancestors[a][i];
            b = ancestors[b][i];
        }
    }
    return ancestors[a][0];
}

// ノード間のホップ数を返す。
// ただし、隣接ノードの場合に1となるような数。
static int hop_count(int a, int b) {
    int c = lca(a, b);
    return depth[a] + depth[b] - 2 * depth[c];
}

// ノード間の経路の長さ。
static int distance(int a, int b) {
    int c = lca(a, b);
    return cost[a] + cost[b] - 2 * cost[c];
}

// DFSにおいて、辺の色ごとに、辺の数と合計長さを辿る。
static int cnt[Max];
static long long sum[Max];

static void dfs2(int v, int p = -1) {
    for (const auto& Q : queries[v]) {
        auto x = -sum[Q.x];
        x += (long long)Q.y * cnt[Q.x];
        ans[Q.qid] += x * Q.coeff;
    }

    for (const auto& E : edge[v]) {
        if (E.dest == p)
            continue;

        cnt[E.color]++;
        sum[E.color] += E.length;

        dfs2(E.dest, v);

        cnt[E.color]--;
        sum[E.color] -= E.length;
    }
}

int main() {
    int n, q;
    cin >> n >> q; // 100'000
    edge.resize(n);
    depth.resize(n, -1);

    for (auto i = 0; i < n - 1; ++i) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        --a, --b;
        edge[a].push_back(Edge{b, c, d});
        edge[b].push_back(Edge{a, c, d});
    }

    init(n);
    ans.resize(q);

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

        auto c = lca(u, v);
        ans[i] = cost[u] + cost[v] - 2 * cost[c];

        queries[u].emplace_back(Query{x, y, u, v, i, 1});
        queries[v].emplace_back(Query{x, y, u, v, i, 1});
        queries[c].emplace_back(Query{x, y, u, v, i, -2});
    }

    dfs2(0);
    for (auto x : ans)
        cout << x << "\n";

    return 0;
}


Measured memory_bytes: 38392