//includes
#include<iostream>
#include<vector>
#include<set>
#include<tuple>
#include<algorithm>
#include<cmath>
#include<string>
#include<stack>
#include<map>
#include<queue>
#include<iomanip>
#include<numeric>
#include<assert.h>
#include<cstring>
#include<unordered_map>
#include<bitset>


template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

//macros and consts
#define REP(i, n) for(int i = 0; i < (int)(n); i++)
#define all(a) (a).begin(),(a).end()
#define FOR(i,a,b) for(int i = (a); i < (b); i++)
#define FORE(i,a) for(auto &i : a)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define accm accumulate
#define Fi first
#define Se second
#define INF 1e9
#define llINF (1LL<<60)
#define mINF -1e9
#define mllINF -(1LL<<60)
#define endl "\n"
#define CONT continue
#define BRK break
#define modulo(n, m) (((n)%(m)+(m))%m)

//shorter types
using namespace std;
using ll = long long;
using vi = std::vector<int>;
using vc = std::vector<char>;
using vll = std::vector<long long>;
using vs = std::vector<string>;
using Mi = map<int,int>;
using Mll = map<ll,ll>;
using UMi = unordered_map<int,int>;
using UMll = unordered_map<ll,ll>;
using Pi = pair<int,int>;
using Pll = pair<ll,ll>;
using vPi = vector<Pi>;
using vPll = vector<Pll>;
using vvi = vector<vector<int>>;
using vvll = vector<vector<ll>>;
using vvc = vector<vector<char>>;
using vvs = vector<vector<string>>;
using pqgi = priority_queue<int,vector<int>,greater<int>>;
using pqsi = priority_queue<int,vector<int>,less<int>>;
using pqgll = priority_queue<int,vector<int>,greater<int>>;
using pssll = priority_queue<int,vector<int>,less<int>>;
template<class T>
using vec = vector<T>;
#define int long long

template<typename T>
struct lca{
	int n, root, l;
	vector<vector<int>> to;
	vector<vector<T>> co;
	vector<int> dep;
	vector<T> costs;
	vector<vector<int>> par;
	lca(int n) : n(n),to(n),co(n),dep(n),costs(n) {
		l = 0;
		while((1 << l) < n){
			l++;
		}
		par = vector<vector<int>>(n + 1,vector<int>(l,n));
	}
	void addEdge(int a, int b, T c = 0){
		to[a].push_back(b);
		co[a].push_back(c);
		to[b].push_back(a);
		co[b].push_back(c);
	}
	void dfs(int v, int d=0, T c = 0,int p = -1){
		if(p != -1) par[v][0] = p;
		dep[v] = d;
		costs[v] = c;
		REP(i,to[v].size()){
			int u = to[v][i];
			if(u == p) continue;
			dfs(u,d+1,c + co[v][i],v);
		}
	}
	void init(int _root = 0){
		root = _root;
		dfs(root);
		REP(i,l-1){
			REP(v,n){
				par[v][i+1] = par[par[v][i]][i];
			}
		}
	}

	int operator()(int a, int b){
		if(dep[a] > dep[b]){
			swap(a,b);
		}
		int gap = dep[b] - dep[a];
		for(int i = l - 1; i >= 0; i--){
			int len = 1 << i;
			if(gap >= len){
				gap -= len;
				b = par[b][i];
			}
		}
		if(a == b){
			return a;
		}
		for(int i = l - 1; i >= 0; i--){
			int na = par[a][i];
			int nb = par[b][i];
			if(na != nb){
				a = na; b = nb;
			}
		}
		return par[a][0];
	}

	int length(int a, int b){
		int c = lca(a,b);
		return dep[a] + dep[b] - dep[c] * 2;
	}
	T dist(int a, int b){
		int c = lca(a,b);
		return costs[a] + costs[b] - costs[c] * 2;
	}
};

const int MX = 100005;
struct Edge{
	int to, co,col;
	Edge(int to,int co,int col) :to(to),co(co),col(col){}
};
vector<Edge> es[MX];
vector<int> ans;

struct Query{
	int col,qid,coef,y;
	Query(int col,int qid, int coef,int y) : col(col),qid(qid),coef(coef),y(y) {}
};
vector<Query> qs[MX];
int cnt[MX];
int sum[MX];

void dfs2(int v, int p = -1){
	for(auto q : qs[v]){
		int x = -sum[q.col];
		x += q.y * cnt[q.col];
		ans[q.qid] += x * q.coef;
	}
	for(auto e : es[v]){
		if(e.to == p) continue;
		cnt[e.col]++;
		sum[e.col] += e.co;
		dfs2(e.to, v);
		cnt[e.col]--;
		sum[e.col] -= e.co;
	}
}



signed main(){
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  int N,Q;
  cin >> N >> Q;
  lca<int> g(N);
  for(int i = 0 ; i < N - 1; i++){
  	int a,b,c,d;
  	cin >> a >> b >> c >> d;
  	a--;
  	b--;
  	es[a].emplace_back(b,d,c);
  	es[b].emplace_back(a,d,c);
  	g.addEdge(a,b,d);
  }
  g.init();
  ans = vector<int>(Q);
  REP(i,Q){
  	int x,y,a,b;
  	cin >> x >> y >> a >> b;
  	a--;b--;
  	int c = g(a,b);
  	ans[i] = g.costs[a] + g.costs[b] - g.costs[c] * 2;
  	qs[a].emplace_back(x,i,1,y);
  	qs[b].emplace_back(x,i,1,y);
  	qs[c].emplace_back(x,i,-2,y);
  }
  dfs2(0);

  REP(i,Q){
  	printf("%lld\n",ans[i]);
  }
  //check types
  //do not eb if you resize
  //resize before you access by idx
  return 0;
} 

Measured memory_bytes: 61168