#include<bits/stdc++.h>
using namespace std;
#define FastRead ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define ll long long int
#define endl '\n'
#define ld long double
#define FOR(i,a,n) for (int i=(a);i<=(n);++i)
#define RFOR(i,a,n) for (int i=(n);i>=(a);--i)
#define FI(i,n) for (int i=0; i<(n); ++i)
#define ZERO(a) memset((a),0,sizeof((a)))
#define MINUS(a) memset((a),-1,sizeof((a)))
#define f first
#define s second
#define pb push_back
#define mk make_pair
#define all(g) g.begin(),g.end()
int fastMax(int x, int y) { return (((y-x)>>(32-1))&(x^y))^y; }
int fastMin(int x, int y) { return (((y-x)>>(32-1))&(x^y))^x; }

// #include <ext/pb_ds/assoc_container.hpp> // Common file
// #include <ext/pb_ds/tree_policy.hpp>     // Including tree_order_statistics_node_updat
// using namespace __gnu_pbds;
// typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

// I am questioning life and universe and 
// everything else after looking at this

const ll MAXN = 1e5 + 10;
const ll LN = 20;
ll par[MAXN][LN],depth[MAXN],Dp[MAXN];
vector<pair<ll,pair<ll,ll>>> graph[MAXN];
ll n,q;

struct node {
    ll val,no;

    node *left,*right;

    node() {}

    node(node *l,node *r,ll v,ll n){
        left = l,right = r,val = v,no = n;
    }
};

node *version[2*MAXN];

void build(node *n,ll s,ll e){
    if(s == e){
        n->val = 0,n->no = 0;
        return;
    }

    ll mid = (s+e)>>1;
    n->left = new node(NULL,NULL,0,0);
    n->right = new node(NULL,NULL,0,0);

    build(n->left,s,mid);
    build(n->right,mid+1,e);

    n->val = 0,n->no = 0;
}

void upgrade(node *prev,node *curr,ll s,ll e,ll idx,ll value){
    if(s > idx || idx > e) return;

    if(s == e){
        curr->val = prev->val + value;
        curr->no = prev->no + 1;
        return;
    }

    ll mid = (s+e)>>1;

    if(idx <= mid){
        curr->right = prev->right;
        curr->left = new node(NULL,NULL,0,0);
        upgrade(prev->left,curr->left,s,mid,idx,value);
    }else {
        curr->left = prev->left;
        curr->right = new node(NULL,NULL,0,0);
        upgrade(prev->right,curr->right,mid+1,e,idx,value);
    }
}

void dfs(ll u,ll p){
    par[u][0] = p;
    Dp[u] = Dp[p] + 1;

    for(auto vv:graph[u]){
        if(vv.first == p) continue;
        upgrade(version[u],version[vv.first],1,n-1,vv.second.first,vv.second.second);
        depth[vv.first] = depth[u] + vv.second.second;
        dfs(vv.first,u);
    }  
}

ll lca__(ll a,ll b){
    if(Dp[a] < Dp[b]) swap(a,b);

    ll diff = Dp[a] - Dp[b];

    FOR(i,0,LN-1) if(diff&(1<<i)) a = par[a][i];

    if(a != b){
        for(ll i = LN-1;i>=0;i--){
            if(par[a][i] != par[b][i]) a = par[a][i],b = par[b][i];
        }

        a = par[a][0];
    }

    return a;
}

node *query(node *i,ll idx,ll s,ll e){
    if(s == e) return i;

    ll mid = (s+e)>>1;

    if(idx <= mid) return query(i->left,idx,s,mid);
    else return query(i->right,idx,mid+1,e);
}

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

    FOR(i,1,n-1){
        ll u,v,c,d; cin>>u>>v>>c>>d;
        graph[u].push_back(make_pair(v,make_pair(c,d)));
        graph[v].push_back(make_pair(u,make_pair(c,d)));
    }

    FOR(i,1,n) version[i] = new node(NULL,NULL,0,0);

    build(version[1],1,n-1);

    depth[1] = 0;
    Dp[0] = -1;

    MINUS(par);

    dfs(1,0);

    FOR(i,0,LN-1) FOR(j,1,n) if(par[j][i] != -1) par[j][i+1] = par[par[j][i]][i];

    while(q--){
        ll x,y,u,v; cin>>x>>y>>u>>v;

        ll lca = lca__(u,v);

        if(lca == 0 || lca == -1) lca = 1;

        ll ans = depth[u] + depth[v] - 2*depth[lca];

        node *a = query(version[u],x,1,n-1);
        node *b = query(version[v],x,1,n-1);
        node *c = query(version[lca],x,1,n-1);

        cout<<ans - (a->val + b->val - 2*(c->val)) + y*(a->no + b->no - 2*(c->no))<<endl;
    }
}

signed main(){

   FastRead;    

    ll t;
    t = 1; 
   // cin>>t;
    FOR(i,1,t){
        // cout<<"Case "<<i<<":\n";
        solve();
    }
}


Measured memory_bytes: 125440