#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define ll long long
#define rep2(i,a,b) for(ll i=a;i<=b;++i)
#define rep(i,n) for(ll i=0;i<n;i++)
#define rep3(i,a,b) for(ll i=a;i>=b;i--)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pq priority_queue
#define pb push_back
#define eb emplace_back
#define vec vector<int>
#define vecll vector<ll>
#define vecpii vector<pii>
#define vec2(a,b) vector<vec>(a,vec(b))
#define vec2ll(a,b) vector<vecll>(a,vecll(b))
#define vec3(a,b,c) vector<vector<vec>>(a,vec2(b,c))
#define vec3ll(a,b,c) vector<vector<vecll>>(a,vec2ll(b,c))
#define fi first
#define se second
#define endl "\n"
#define all(c) begin(c),end(c)
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define lb(c,x) distance(c.begin(),lower_bound(all(c),x))
#define ub(c,x) distance(c.begin(),upper_bound(all(c),x))
#define MM " "
using namespace std;
int in() {int x;cin>>x;return x;}
ll lin() {ll x;cin>>x;return x;}
template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
template<class T> inline void print(pair<T,T> p){cout<<"("<<p.first<<","<<p.second<<") ";}
template<class T> inline void print(vector<pair<T,T>> v){for(auto e:v)print(e); cout<<endl;}
template<class T> inline void print(T v){for(auto e:v)cout<<e<<" ";cout<<endl;}

struct edge{
    int to,c,d;
};
template< typename G >
struct DoublingLowestCommonAncestor {
  const int LOG;
  vector< int > dep;
  const G &g;
  vector< vector< int > > table;

  DoublingLowestCommonAncestor(const G &g) : g(g), dep(g.size()), LOG(32 - __builtin_clz(g.size())) {
    table.assign(LOG, vector< int >(g.size(), -1));
  }

  void dfs(int idx, int par, int d) {
    table[0][idx] = par;
    dep[idx] = d;
    for(auto &t : g[idx]) {
        int to=t.to;
      if(to != par) dfs(to, idx, d + 1);
    }
  }

  void build() {
    dfs(0, -1, 0);
    for(int k = 0; k + 1 < LOG; k++) {
      for(int i = 0; i < table[k].size(); i++) {
        if(table[k][i] == -1) table[k + 1][i] = -1;
        else table[k + 1][i] = table[k][table[k][i]];
      }
    }
  }

  int query(int u, int v) {
    if(dep[u] > dep[v]) swap(u, v);
    for(int i = LOG - 1; i >= 0; i--) {
      if(((dep[v] - dep[u]) >> i) & 1) v = table[i][v];
    }
    if(u == v) return u;
    for(int i = LOG - 1; i >= 0; i--) {
      if(table[i][u] != table[i][v]) {
        u = table[i][u];
        v = table[i][v];
      }
    }
    return table[0][u];
  }
};


vector<vector<edge>> g;
struct process{
    int id,t,col,y;
};
vec ans;
vector<vector<process>> mem;
int tmp;
vec colnum,colsum;
int dfs(int x,int p,int c,int d){
    tmp+=d; colnum[c]++; colsum[c]+=d;
    for(auto e:mem[x]){
        ans[e.id]+=e.t*(tmp-colsum[e.col] + colnum[e.col]*e.y);
    }
    for(auto e:g[x]){
        if(e.to!=p)
        dfs(e.to,x,e.c,e.d);
    }
    tmp-=d; colnum[c]--; colsum[c]-=d;
}

void go(){
    int n=in();
    g.resize(n);
    colnum.resize(n+1),colsum.resize(n+1);
    int q=in();
    ans.resize(q);
    rep(i,n-1){
        int a=in()-1,b=in()-1,c=in(),d=in();
        g[a].pb(edge{b,c,d});
        g[b].pb(edge{a,c,d});
        // cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
    }
    DoublingLowestCommonAncestor<vector<vector<edge>>> lca(g);
    lca.build();
    mem.resize(n+1);
    for (int i = 0; i < q; i++){
        int x=in(),y=in(),u=in()-1,v=in()-1;
        int p=lca.query(u,v);
        mem[u].pb(process{i,1,x,y});
        mem[v].pb(process{i,1,x,y});
        mem[p].pb(process{i,-2,x,y});
    }
    dfs(0,-1,0,0);
    print(ans);
}
        



main(){
    ios
    int Testcases=1;
    while(Testcases--){
        go();
    }
    return 0;
}


Measured memory_bytes: 29044