#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <climits>
#include <cstring>

#define rep(i, m, n) for(int i=int(m);i<int(n);i++)
#define all(c) begin(c),end(c)

template<typename T1, typename T2>
inline void chmin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void chmax(T1 &a, T2 b) { if (a < b) a = b; }

typedef long long int ll;
using ll = long long int;
using ull = long long unsigned int;
using Int = long long int;
using namespace std;
#define INF (1 << 30) - 1
#define INFl (ll)5e15
#define DEBUG 0
#define dump(x)  cerr << #x << " = " << (x) << endl
#define MOD 1000000007


//edit
class Mo {
    vector<int> queryL;
    vector<int> queryR;
    vector<int> idx;
    int pt = 0;
    int ql = 0, qr = 0;

public:
    // [l, r)
    void insert(int l, int r) {
        queryL.push_back(l);
        queryR.push_back(r);
        if (idx.empty()) idx.push_back(0);
        else idx.push_back(idx.back() + 1);
    }

    void build() {
        int K = (int) round(sqrt(idx.size()));
        sort(all(idx), [&](int x, int y) {
            if (queryL[x] / K == queryL[y] / K) {
                return queryR[x] < queryR[y];
            } else {
                return queryL[x] < queryL[y];
            }
        });
    }

    int query() {
        if (pt >= idx.size()) return -1;
        while (qr < queryR[idx[pt]]) add(qr++);
        while (ql > queryL[idx[pt]]) add(--ql);

        while (qr > queryR[idx[pt]]) del(--qr);
        while (ql < queryL[idx[pt]]) del(ql++);

        return idx[pt++];
    }

    void add(int x);

    void del(int x);
};

struct edge {
    int from;
    int to;
    int id;
    int c; // color
    int w; // weight
};

//vector<int> vert;
//vector<int> id; //辺id

vector<int> in; //初めて入る
vector<bool> pal; //辺の使用回数のパリティ
vector<edge> edges;
Int sum = 0;
vector<Int> col; // ある辺の総和
vector<Int> cnt; // ある色の個数

void Mo::add(int x) {
    int id = edges[x].id;
    pal[id] = !pal[id];
    if (pal[id]) {
        cnt[edges[x].c]++;
        col[edges[x].c] += edges[x].w;
        sum += edges[x].w;
    } else {
        cnt[edges[x].c]--;
        col[edges[x].c] -= edges[x].w;
        sum -= edges[x].w;
    }
}

void Mo::del(int x) {
    add(x);
}


class Solve {
public:
    struct query {
        Int x, y, u, v;
    };

    Int N, Q;
    vector<vector<edge>> treeone;

    void dfs(edge e, int p = -1) {
        in[e.to] = edges.size();
        edges.push_back(e);
        for (auto next_edge : treeone[e.to]) {
            if (next_edge.to != p) {
                dfs(next_edge, e.to);
                auto next_edge2 = next_edge;
                swap(next_edge2.to, next_edge2.from);
                edges.push_back(next_edge2);
            }
        }
    }


    void solve() {
        cin >> N >> Q;
        treeone.resize(N);
        in.resize(N);
        pal.resize(N);
        col.resize(N);
        cnt.resize(N);
        for (int i = 0; i + 1 < N; ++i) {
            int a, b, c, d;
            cin >> a >> b >> c >> d;
            a--, b--;
            treeone[a].push_back(edge{a, b, i + 1, c, d});
            treeone[b].push_back(edge{b, a, i + 1, c, d});
        }

        edge fedge{-1, 0, 0, -1, 0};
        dfs(fedge);

        vector<query> queries(Q);
        for (int i = 0; i < Q; ++i) {
            Int x, y, u, v;
            cin >> x >> y >> u >> v;
            u--, v--;
            queries[i] = {x, y, u, v};
        }

        Mo ei1333;
        for (int i = 0; i < Q; ++i) {
            int u = in[queries[i].u];
            int v = in[queries[i].v];
            if (u > v) swap(u, v);
            int l, r;
            l = u + 1;
            r = v + 1;
            ei1333.insert(l, r);
        }

        vector<Int> ans(Q);
        ei1333.build();
        for (int i = 0; i < Q; ++i) {
            int idx = ei1333.query();
            int x = queries[idx].x;
            int y = queries[idx].y;
            ans[idx] = sum - col[x] + cnt[x] * y;//kotaewoireru
        }

        for (int i = 0; i < Q; ++i) {
            cout << ans[i] << endl;
        }


    }
};


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

    Solve().solve();


    return 0;
}


Measured memory_bytes: 32748