#include <bits/stdc++.h>


using namespace std;
#define rep(i,n) for (int i = 0; i < (int)(n); ++i)
#define reps(i,n) for (int i = 1; i <= (int)(n); ++i)
#define repd(i,n) for (int i = (int)(n - 1); i >= 0; --i)
#define repds(i,n) for(int i = (int)(n); i > 0; --i)
#define all(f,x,...) [&](decltype(x)& whole) { return (f)(begin(x), end(x), ##__VA_ARGS__); }(x)
#define rall(f,x,...) [&](decltype(x)& whole) { return (f)(rbegin(x), rend(x), ##__VA_ARGS__); }(x)
using ll = long long;
using ld = long double;
constexpr ll inf = static_cast<ll>(1e17);
constexpr int iinf = static_cast<int>(1e9);
constexpr double dinf = 1e10;
constexpr ld ldinf = 1e17;
ll mod = static_cast<ll>(1e9 + 7);
std::ostream& endn(std::ostream& os) { return os.put(os.widen('\n')); }
template<class T>
constexpr int sz(const T& a) { return (int)a.size(); }
template<class T, class ... Args>
constexpr void mins(T& a, Args... args) { a = min<T>({ a, args... }); }
template<class T, class... Args>
constexpr void maxs(T& a, Args... args) { a = max<T>({ a,args... }); }
template<class T>
constexpr T ceils(const T a, const T b) { return (a + b - 1) / b; }
ll plusMod(ll& a, const ll b) { return a = (a % mod + b % mod) % mod; }
template<typename A, size_t N, typename T>
constexpr void fillArray(A(&array)[N], const T& val) { std::fill((T*)array, (T*)(array + N), val); }

template<class T>
class LCA {
public:
    LCA() :root(0), V(0), logV(0), to(0), parent(0), depth(0) {}
    LCA(int v, int r = 0) :root(r), V(v), logV((int)std::ceil(std::log2(v)) + 1),
        to(v, std::vector<Edge>(0)), parent(logV, std::vector<int>(v, 0)), depth(v, 0), dist(v, 0) {}

    void resize(int v, int r = 0) {
        *this = { v,r };
    }

    void addEdge(int a, int b, T c = 1) {
        to[a].emplace_back(b, c);
        to[b].emplace_back(a, c);
    }

    void init() {
        dfs(root, -1, 0);

        for (int k = 0; k + 1 < logV; ++k)
            for (int i = 0; i < V; ++i)
                if (parent[k][i] < 0)
                    parent[k + 1][i] = -1;
                else
                    parent[k + 1][i] = parent[k][parent[k][i]];
    }

    int operator()(int u, int v) {
        if (depth[u] > depth[v])
            std::swap(u, v);

        for (int k = 0; k < logV; ++k)
            if ((depth[v] - depth[u]) >> k & 1)
                v = parent[k][v];

        if (u == v)
            return u;

        for (int k = logV - 1; k >= 0; --k)
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }

        return parent[0][u];
    }

    T length(int u, int v) {
        int c = (*this)(u, v);
        return dist[u] + dist[v] - dist[c] * 2;
    }

private:
    void dfs(int v, int p = -1, int d = 0, T c = 0) {
        parent[0][v] = p;
        depth[v] = d;
        dist[v] = c;
        int n = (int)to[v].size();
        for (int i = 0; i < n; ++i) {
            auto ne = to[v][i];
            if (ne.to != p)
                dfs(ne.to, v, d + 1, c + ne.cost);
        }
    }

    struct Edge {
        int to;
        T cost;
        Edge() :to(0), cost(1) {}
        Edge(int t, T c) :to(t), cost(c) {}
    };

    int root, V, logV;
    std::vector<std::vector<Edge>> to;
    std::vector<std::vector<int>> parent;
    std::vector<int> depth;
    std::vector<T> dist;

};

struct Edge
{
    int to, color;
    ll cost;
    Edge(int t, int col, ll cos) :to(t), color(col), cost(cos) {}
};

struct Query {
    int id;
    bool isV;
    Query(int i, bool v) :id(i), isV(v) {}
};

LCA<ll> lca;
int n, q;
vector<Edge> g[100005];
vector<Query> query[100005];
int x[100005], u[100005], v[100005];
ll y[100005];
int qnum[100005];
ll qsum[100005];
int num[100005];
ll sum[100005];
void dfs(int v = 0, int p = -1) {
    rep(i, query[v].size()) {
        auto que = query[v][i];
        if (que.isV) {
            qnum[que.id] += num[x[que.id]];
            qsum[que.id] += sum[x[que.id]];
        }
        else {
            qnum[que.id] -= 2 * num[x[que.id]];
            qsum[que.id] -= 2 * sum[x[que.id]];
        }
    }

    rep(i, g[v].size()) {
        auto ne = g[v][i];
        if (ne.to != p) {
            ++num[ne.color];
            sum[ne.color] += ne.cost;
            dfs(ne.to, v);
            --num[ne.color];
            sum[ne.color] -= ne.cost;
        }
    }
}

void solve() {
    cin >> n >> q;

    lca.resize(n);
    rep(i, n - 1) {
        int a, b, c;
        ll d;
        cin >> a >> b >> c >> d;

        --a, --b;
        lca.addEdge(a, b, d);
        g[a].emplace_back(b, c, d);
        g[b].emplace_back(a, c, d);
    }

    lca.init();
    rep(i, q) {
        cin >> x[i] >> y[i] >> u[i] >> v[i];

        --u[i], --v[i];
        auto c = lca(u[i], v[i]);
        query[u[i]].emplace_back(i, true);
        query[v[i]].emplace_back(i, true);
        query[c].emplace_back(i, false);

    }

    dfs();

    rep(i, q)
        cout << lca.length(u[i], v[i]) - qsum[i] + y[i] * qnum[i] << endn;

}


int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);

    solve();

    cout << flush;

    return 0;
}


Measured memory_bytes: 40184