bool DBG = false;
#include<bits/stdc++.h>
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")

//#include <boost/multiprecision/cpp_dec_float.hpp>
//#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using ll = long long;
using ld = long double;
//using i128 = __int128_t;
//using bint = boost::multiprecision::cpp_int
//using d1024 = boost::multiprecision::number<mp::cpp_dec_float<1024>>;
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define IFOR(i,a,b) for(int i=((b)-1);i>=(a);--i)
#define RPT(i,a,b) for(int i=(a);i<((a)+(b));++i)
#define IRPT(i,a,b) for(int i=((a)+(b)-1);i>=(a);--i)
#define ALL(x) x.begin(),x.end()
#define RALL(x) x.rbegin(),x.rend()
#define fs first
#define sd second
#define couts(x) cout << (x) << (" ")
#define coutn(x) cout << (x) << ("\n")
#define ncouts(x) numout(x),outst[outst_N++] = ' '
#define ncoutn(x) numout(x),outst[outst_N++] = '\n'
#define scouts(x) strout(x),outst[outst_N++] = ' '
#define scoutn(x) strout(x),outst[outst_N++] = '\n'
#define dcouts(x) if(DBG) couts(x)
#define dcoutn(x) if(DBG) coutn(x)
#define endl "\n"
#define psb push_back
#define ppb pop_back
#define eb emplace_back
#define lb lower_bound
#define ub upper_bound
#define LBIT(x,a) (((x)>>(a))&1LL)
#define IBIT(x,a) (((x)>>(a))&1)
#define BCOUNT(x) (__builtin_popcount(x))
template<typename T> std::istream &operator>>(std::istream &is, std::vector<T> &vec){ for (auto &v : vec) is >> v; return is; }
template<typename T1, typename T2> std::istream &operator>>(std::istream &is, std::pair<T1,T2> &p){is >> p.first >> p.second; return is; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec){ os << "["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::deque<T> &vec){ os << "deque["; for (auto v : vec) os << v << ","; os << "]"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_set<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T> std::ostream &operator<<(std::ostream &os, const std::unordered_multiset<T> &vec){ os << "{"; for (auto v : vec) os << v << ","; os << "}"; return os; }
template<typename T1, typename T2> std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa){ os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
template<typename TK, typename TV> std::ostream &operator<<(std::ostream &os, const std::unordered_map<TK, TV> &mp){ os << "{"; for (auto v : mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }
/*
std::ostream &operator<<(std::ostream &os, const i128 nu){
  i128 co = nu;
  if(co==0){cout << '0';}
  else{
    string ous; if(co<0){cout<<'-'; co*=-1;}
    while(co){
      ous += (co%10)+'0';
      co /= 10;
    }
    reverse(ALL(ous));
    cout<<ous;
  }
  return os;
}
std::istream &operator>>(std::istream &is, i128 &nu){ string cs; cin >> cs; nu=0;int mn=1; for(auto &x:cs) { if(x!='-'){nu*=10;nu+=(x-'0');} else mn *= -1;} nu *= mn;  return is; }

*/


template<class T> using V = vector<T>;
template<class T> using V2 = V<V<T>>;
template<class T> using V3 = V<V2<T>>;
template<class T> using V4 = V<V3<T>>;


char outst[20'000'000]; int outst_N = 0;
char outst_tmp[200];
template<class NUM >
void numout(NUM n){
  if(n<0) { n*=-1; outst[outst_N++] = '-';}
  if(n==0){ outst[outst_N++] = '0'; return;}
  int cnt = 0;
  while(n>0){
    outst_tmp[cnt++] = '0' + (n % 10);
    n /= 10;
  }
  IFOR(i,0,cnt){
    outst[outst_N++] = outst_tmp[i];
  }
}
void strout(std::string s){
  for(auto x: s){
    outst[outst_N++] = x;
  }
}

constexpr ll LINF = 1LL << 60;
constexpr int IINF = 1 << 28;
//constexpr ll mod =  1'000'000'007;
constexpr ll mod = 998244353;



struct edge{
  int to, color; ll len;
  edge(int to, int  color, ll len) : to(to), color(color), len(len)  {}
};
struct query{
  int kind, id,  color; ll len;
  query(int kind, int id, int color, ll len) : kind(kind), id(id), color(color), len(len) {}
};
int n;
V2<edge> g;
V2<query> qv;
V< ll > query_ans;
V< ll > nums; V< ll > lens;


struct LCA{
  V<int> depth; V2<int> par; V<ll> dist;
  void dfs(int v, int p, int d){
    par[0][v] = p;
    depth[v] = d;
    for(auto &x: g[v]){
      if(x.to==p) continue;
      dist[x.to] = min<ll>(dist[x.to], dist[v] + x.len );
      dfs(x.to, v, d+1);
    }
  }
  void init(){
    depth = V<int>(n);
    dist = V<ll>(n, LINF); dist[0] = 0;
    par = V2<int>(30, V<int>(n,-1));
    dfs(0,-1,0);
    FOR(k,0,28){
      FOR(v,0,n){
        if(par[k][v]<0) par[k+1][v] = -1;
        else par[k+1][v] = par[k][ par[k][v] ]; 
      }
    }
  }
  int lca(int u, int v){
    if(depth[u]>depth[v]) swap(u,v);
    FOR(k,0,28){
      if( (depth[v]-depth[u]) >> k & 1){
        v = par[k][v];
      }
    }
    if(u==v) return u;
    IFOR(k,0,28){
      if(par[k][u] != par[k][v]){
        u = par[k][u];
        v = par[k][v];
      }
    }
    return par[0][u];
  }
};

void dfs(int s, int par = -1){
  for(auto &x: g[s]){
    if(x.to==par) continue;
    nums[x.color]++;
    lens[x.color]+=x.len;
    
    for(auto &y: qv[x.to]){
      query_ans[y.id] -= y.kind * lens[y.color];
      query_ans[y.id] += (ll)y.kind * y.len * nums[y.color];
    }
    
    dfs(x.to,s);
    nums[x.color]--;
    lens[x.color]-=x.len;
  }
}


void solve(){
  int q; cin >> n >> q;
  g = V2<edge>(n);
  FOR(i,0,n-1){
    int a, b, c; ll d; cin >> a >> b >> c >> d;
    --a, --b, --c;
    g[a].eb(b,c,d);
    g[b].eb(a,c,d);
  }
  LCA lca;
  lca.init();
  
  query_ans = V<ll>(q);
  qv = V2<query>(n);
  nums = V<ll>(n); lens = V<ll>(n);
  FOR(i,0,q){
    int a, b, c; ll d; cin >> c >> d >> a >> b;
    --a, --b, --c;
    qv[a].eb(1,i,c,d);
    qv[b].eb(1,i,c,d);
    qv[lca.lca(a,b)].eb(-2,i,c,d);
    query_ans[i] += lca.dist[a];
    query_ans[i] += lca.dist[b];
    query_ans[i] -= 2*lca.dist[ lca.lca(a,b) ];
  }
  
  dfs(0);
  
  FOR(i,0,q){
    coutn(query_ans[i]);
  }
  
  
}




int main(void){
  //std::cout << std::fixed << std::setprecision(20);
  cin.tie(0);
  //ios::sync_with_stdio(false);
  solve();
  //printf("%s", outst);
  return 0;
}




Measured memory_bytes: 40180