#include <stdio.h>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <list>
#include <iterator>
#include <assert.h>
#pragma warning(disable:4996) 

typedef long long ll;
#define MIN(a, b) ((a)>(b)? (b): (a))
#define MAX(a, b) ((a)<(b)? (b): (a))
#define LINF 9223300000000000000
#define INF 2140000000
const long long MOD = 1000000007;
using namespace std;

int n,q;
vector<vector<pair<int,int> > > g;   // to,edge

vector<int> d;    // depth
vector<vector<int> > anc;    // anc[i][j]: vertex i の 2^j個上の祖先

// data for each query
vector<int> x,y,u,v,C,D,a;   // a: LCA
vector<ll> ans;

vector<int> cnt;   // current edge num in the path from root for each color
vector<ll> dist;   // current dist sum in the path from root for each color 
ll dist0;          // current dist from root

vector<vector<pair<int,int> > > chk;   // chk[i](0<=i<n): (queryID, mult)の列

void dfs0( int par, int curr, vector<int>& vv )   // vv: rootからのnode列、anc: 1,2,4,8,..上の祖先
{
    d[curr]=(int)vv.size();
    int k=1;
    while(k<=d[curr]) {
        anc[curr].push_back(vv[d[curr]-k]);
        k*=2;
    }

    vv.push_back( curr );
    int siz=(int)g[curr].size();
    int i;
    for(i=0; i<siz; i++) {
        int next = g[curr][i].first;
        if( next != par ) {
            dfs0( curr, next, vv );
        }
    }
    vv.pop_back();
    return;
}

int getLCA( int a, int b )
{
    if(d[a]>d[b]) swap(a, b);
    int delta = d[b]-d[a];
    int cnt=0;
    while(delta>0) {
        if(delta & (1<<cnt)) {
            b = anc[b][cnt];
            delta -= (1<<cnt);
        }
        cnt++;
    }
    assert(d[a]==d[b]);
    if(a==b) return a;

    int N=(int)anc[a].size();
    int i;
    for(i=N-1; i>=0; i--) {
        if((int)anc[a].size()>i) {
            if(anc[a][i]!=anc[b][i]) {
                a = anc[a][i];
                b = anc[b][i];
            }
        }
    }
    return anc[a][0];
}


void dfs2( int par, int curr)
{
    int siz=chk[curr].size();
    int i;
    for(i=0; i<siz; i++) {
        int id = chk[curr][i].first;
        int mult = chk[curr][i].second;
        ans[id] += mult*(dist0 - dist[x[id]] + cnt[x[id]] * y[id]);
    }

    for(i=0; i<(int)g[curr].size(); i++) {
        int next = g[curr][i].first;
        int edge = g[curr][i].second;
        if( next != par ) {
            cnt[C[edge]]++;
            dist[C[edge]]+=D[edge];
            dist0+=D[edge];
            dfs2( curr, next );
            cnt[C[edge]]--;
            dist[C[edge]]-=D[edge];
            dist0-=D[edge];
        }
    }

    return;
}

int main(int argc, char* argv[])
{
    scanf("%d%d", &n, &q);

    g.resize(n);
    d.resize(n);
    anc.resize(n);
    C.resize(n-1);
    D.resize(n-1);
    int i;
    for(i=0; i<n-1; i++) {
        int a,b;
        scanf("%d%d%d%d", &a, &b, &C[i], &D[i]);
        g[a-1].push_back(make_pair(b-1,i));
        g[b-1].push_back(make_pair(a-1,i));
    }

    vector<int> vv;
    dfs0(-1, 0, vv );

    chk.resize(n);
    x.resize(q);
    y.resize(q);
    u.resize(q);
    v.resize(q);
    a.resize(q);
    ans.resize(q);
    for(i=0; i<q; i++) {
        scanf("%d%d%d%d", &x[i], &y[i], &u[i], &v[i]);
        u[i]--; v[i]--;
        a[i] = getLCA(u[i],v[i]);
        chk[u[i]].push_back(make_pair(i,1));
        chk[v[i]].push_back(make_pair(i,1));
        chk[a[i]].push_back(make_pair(i,-2));
    }
    cnt.resize(n);
    dist.resize(n);

    dfs2(-1, 0);

    for(i=0; i<q; i++) {
        printf("%lld\n", ans[i]);
    }
    return 0;
}


Measured memory_bytes: 33528