#include <bits/stdc++.h>

using namespace std;

/* g++ -g -fsanitize=address -lasan -std=c++11 -Dfoo_ */

/* freopen("input.txt", "rt", stdin); */
/* freopen("output.txt", "wt", stdout); */

#define ALL(c)          (c).begin(), (c).end()
#define ALLR(c)         (c).rbegin(), (c).rend()
#define FOR(i,a,b)      for (int i=(a); i < (b); ++i)
#define FORR(i,a,b)     for (int i=(a); i > (b); --i)
#define FOR_ALL(i,c)    for (__typeof((c).begin()) i=(c).begin();   \
                             i != (c).end(); ++i)
#define FOR_ALLR(i,c)   for (__typeof((c).rbegin()) i=(c).rbegin(); \
                             i != (c).rend(); ++i)
#define SZ(array)       (sizeof(array)/sizeof(array[0]))
#define lc(x)           (x<<1)     /* 2*x */
#define rc(x)           (x<<1 | 1) /* 2*x+1 */
#define lowbit(x)       (x & (-x)) /* 0b10100 -> 0b100 */

typedef long long       LL;
typedef map<int,int>    MII;
typedef pair<int,int>   PII;
typedef set<int>        SI;
typedef vector<bool>    VB;
typedef vector<double>  VD;
typedef vector<int>     VI;
typedef vector<string>  VS;

/* check if a key is in container C */
template <class C>
inline bool in_(const typename C::key_type& k, const C& A)
{ return A.find(k) != A.end(); }
inline bool in_(const string& s, const string& S)
{ return S.find(s) != string::npos; }

const int maxm = 20;
const int maxn = 1e5+1000;
struct edge { int v,c,d; } E[maxn*2];
int P[maxn][maxm], deep[maxn], label[maxn], dist[maxn];
int segtreec[maxn*4], segtreed[maxn*4];
VI G[maxn]; vector<PII> colrc[maxn], colrd[maxn];

void dfs(const int u, const int p, int& stamp)
{
    FOR(i,1,maxm) if (deep[u] >= (1<<i))
        P[u][i] = P[P[u][i-1]][i-1];
    FOR_ALL(e,G[u]) {
        const int v = E[*e].v;
        const int c = E[*e].c;
        const int d = E[*e].d;
        if (v != p) {
            P[v][0] = u;
            stamp++;
            label[v] = stamp;
            colrc[c].push_back(PII(stamp,+1));
            colrd[c].push_back(PII(stamp,+d));
            dist[v] = dist[u]+d;
            deep[v] = deep[u]+1;
            dfs(v,u,stamp);
            stamp++;
            colrc[c].push_back(PII(stamp,-1));
            colrd[c].push_back(PII(stamp,-d));
        }
    }
}

int lca(int u, int v)
{
    if (deep[u] < deep[v])
        swap(u,v);
    const int d = deep[u]-deep[v];
    FOR(i,0,maxm) if (d & (1<<i))
        u = P[u][i];
    if (u == v)
        return u;
    FORR(i,maxm-1,-1) if (P[u][i] != P[v][i])
        u = P[u][i], v = P[v][i];
    return P[u][0];
}

/* set A[i] = value */
void update(int i, const int value, const int n, int tree[])
{
    /* pushup from leaf node */
    for (tree[i += n] = value; i > 1; i >>= 1)
        tree[i>>1] = tree[i] + tree[i^1];
}

/* sum on interval [i,j) */
int query(int i, int j, const int n, int tree[])
{
    int ans = 0;
    for (i += n, j += n; i < j; i >>= 1, j >>= 1) {
        if (i&1) ans += tree[i++];
        if (j&1) ans += tree[--j];
    }
    return ans;
}

void setvalue(const int x, const int size, const bool zero)
{
    FOR_ALL(c,colrc[x])
        update(c->first, zero ? 0 : c->second, size, segtreec);
    FOR_ALL(d,colrd[x])
        update(d->first, zero ? 0 : d->second, size, segtreed);
}

int getvalue(
    const int u, const int v, const int w, const int size, int tree[])
{
    const int a = query(0,label[u]+1, size, tree);
    const int b = query(0,label[v]+1, size, tree);
    const int c = query(0,label[w]+1, size, tree);
    const int ans = a + b - 2*c;
    return ans;
}

int main()
{
#ifdef foo_
    freopen("foo", "rt", stdin);
#endif
    ios::sync_with_stdio(false);
    int n,q;
    while (cin >> n >> q) {
        const int size = 2*n+5;
        FOR(i,0,2*size)
            segtreec[i] = segtreed[i] = 0;
        FOR(i,0,n+1) 
            G[i].clear(), colrc[i].clear(), colrd[i].clear();
        int e = 0;
        FOR(i,0,n-1) {
            int a,b,c,d; cin >> a >> b >> c >> d;
            G[a].push_back(e);
            E[e].v = b; E[e].c = c; E[e].d = d; e++;
            G[b].push_back(e);
            E[e].v = a; E[e].c = c; E[e].d = d; e++;
        }
        dist[1] = 0; int stamp = 0;
        dfs(1,0,stamp);
        queue<int> Q[n];
        FOR(i,0,q) {
            int x,y,u,v; cin >> x >> y >> u >> v;
            Q[x].push(i), Q[x].push(y), Q[x].push(u), Q[x].push(v);
        }
        vector<int> ans(q);
        FOR(x,1,n) {
            setvalue(x,size,false);
            while (Q[x].size()) {
                const int i = Q[x].front(); Q[x].pop();
                const int y = Q[x].front(); Q[x].pop();
                const int u = Q[x].front(); Q[x].pop();
                const int v = Q[x].front(); Q[x].pop();
                const int w = lca(u,v);
                ans[i] += dist[u] + dist[v] - 2*dist[w];
                ans[i] -= getvalue(u,v,w,size,segtreed);
                ans[i] += getvalue(u,v,w,size,segtreec) * y;
            }
            setvalue(x,size,true);
        }
        FOR(i,0,q)
            cout << ans[i] << endl;
    }
    return 0;
}


Measured memory_bytes: 99348