#include<bits/stdc++.h>
#define FOR0(i,n) for(i=0;i<n;i++)
#define FOR(i,j,n) for(i=j;i<n;i++)
#define FORD(i,j,k) for(i=j;i>=k;i--)
#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define inf 1000000000
#define ninf -1000000000
#define endl '\n' 
#define she_told_me_dont_worry ios_base::sync_with_stdio (false) ; cin.tie(0) ; cout.tie(0) ;
// Use cout.flush() for interactive problems.
// Use this for increased stack size: g++ -o a.exe -Wl,--stack=256000000 -O2 source.cpp
inline long long  MAX2(long long  a, long long int b){return (a)>(b)?(a):(b);}
inline long long  MAX3(long long  a, long long  b,long long  c){return (a)>(b)?((a)>(c)?(a):(c)):((b)>(c)?(b):(c));}
inline long long  MIN2(long long  a, long long  b){return (a)<(b)?(a):(b);}
inline long long  MIN3(long long  a, long long b,long long c){return (a)<(b)?((a)<(c)?(a):(c)):((b)<(c)?(b):(c));}
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector< ii > vii;
typedef struct edge
{
    int u, c, d;
    edge(int x, int y, int z)
    {
        u = x;
        c = y;
        d = z;
    }
} Edge;
vector< vector< Edge > > graph(100005);
int tin[100005], tout[100005];
int timer = 0;
vector< map< int, ii > > colors(100005);
vector < Edge > parent;
int block = 0;
int up[100005][20];
int depth[100005];
int dis[100005] = {};
map <int ,ii > cur;
void dfs(int i, int p, int d)
{
    tin[i] = ++timer;
    int j, si = graph[i].size();
    up[i][0] = p;
    depth[i] = d;
    if(i != 0)
    {
        dis[i] = dis[p] + parent[i].d;
        cur[parent[i].c].ff++;
        cur[parent[i].c].ss += parent[i].d;
    }
    if(d%block == 0)
        colors[i] = cur;
    FOR(j, 1, 18)
    {
        up[i][j] = up[up[i][j-1]][j-1];
    }
    FOR0(j, si)
    {
        Edge v = graph[i][j];
        if( v.u == p ) continue;
        parent[v.u] = Edge(i, v.c, v.d);
        dfs(v.u, i, d+1);
    }
    if(i != 0)
    {
        cur[parent[i].c].ff--;
        cur[parent[i].c].ss -= parent[i].d;
    }
    tout[i] = ++timer;
}
bool is_ancestor(int a, int b)
{
    if(tin[a] <= tin[b] && tout[a] >= tout[b])
        return true;
    return false;
}
int lca(int a, int b)
{
    if(is_ancestor(a, b)) return a;
    if(is_ancestor(b, a)) return b;
    int i;
    FORD(i, 17, 0)
    {
        if(!is_ancestor(up[a][i], b))
            a = up[a][i];
    }
    return up[a][0];
}
int get_val(int a, int c, int val)
{
    int d = 0, x = 0, y = 0;
    int res = 0;
    if(depth[a]%block == 0)
    {
        y += colors[a][c].ss;
        x += colors[a][c].ff;
        d += dis[a];
        res = d + x*val - y;
    }
    else 
    {
        d += parent[a].d;
        if(parent[a].c == c)
        {
            x ++;
            y += parent[a].d;
        }
        res = d + x*val - y;
        res += get_val(parent[a].u, c, val);
    }
    return res;
}
int compute(int x, int y, int u, int v)
{
    int ancestor = lca(u, v);
    int uval = get_val(u, x, y);
    int vval = get_val(v, x, y);
    int aval = get_val(ancestor, x, y);
    return uval + vval - 2*aval;
}
int main()
{
    she_told_me_dont_worry
    int n, q;
    cin>>n>>q;
    block = sqrt(n);
    int i;
    FOR0(i, n)
        parent.push_back(Edge(0, 0, 0));

    FOR0(i, n-1)
    {
        int a, b, c, d;
        cin>>a>>b>>c>>d;
        a--;b--;
        graph[a].push_back(Edge(b, c, d));
        graph[b].push_back(Edge(a, c, d));
    }
    dfs(0, 0, 0);
    while(q--)
    {
        int x, y, a, b;
        cin>>x>>y>>a>>b;
        a--;b--;
        ll ans = compute(x, y, a, b);
        cout<<ans<<endl;
    }
    cerr <<endl<< "Time elapsed : " << clock() * 1000.0 / CLOCKS_PER_SEC << " ms" << '\n';
}

Measured memory_bytes: 459488