#include <bits/stdc++.h>
using namespace std;

#define rep(i,m,n) for(int (i)=(int)(m);i<(int)(n);++i)
#define rep2(i,m,n) for(int (i)=(int)(n)-1;i>=(int)(m);--i)
#define REP(i,n) rep(i,0,n)
#define REP2(i,n) rep2(i,0,n)
#define FOR(i,c) for(decltype((c).begin())i=(c).begin();i!=(c).end();++i)
#define all(hoge) (hoge).begin(),(hoge).end()
#define en '\n'
using ll = long long;
using ull = unsigned long long;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
typedef pair<ll, ll> P;
constexpr long long INF = 1LL << 60;
constexpr int INF_INT = 1 << 25;
constexpr long long MOD = (ll) 1e9 + 7;
//constexpr long long MOD = 998244353LL;
using ld=long double;
static const ld pi = 3.141592653589793L;
typedef vector<ll> Array;
typedef vector<Array> Matrix;


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;
}

struct Edge {
	ll to, cap, rev, col;
	Edge(ll _to, ll _cap, ll _rev, ll _col) {
	to = _to; cap = _cap; rev = _rev; col=_col;
	}
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;

void add_edge(Graph& G, ll from, ll to, ll cap, bool revFlag, ll revCap, ll col) {
	G[from].push_back(Edge(to, cap, (ll)G[to].size(), col));
	if (revFlag)G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1, col));
}


//HLD
class HLD {
private:
	Graph& g;
	int n, root;
	vector<int> sz, par, in, out, head, rev, dep;
	void dfs_sz(int v, int p) {
		sz[v] = 1, par[v] = p;
		for (auto& e : g[v]) {
			if (e.to == p)swap(e, g[v].back());
			if (e.to == p)continue;
			dep[e.to] = dep[v] + 1;
			dfs_sz(e.to, v);
			sz[v] += sz[e.to];
			if (sz[e.to] > sz[g[v][0].to])swap(e, g[v][0]);
		}
	}
	void dfs_hld(int v, int p, int& t) {
		in[v] = t++; rev[in[v]] = v;
		for (auto e : g[v]) {
			if (e.to == p)continue;
			head[e.to] = (e.to == g[v][0].to ? head[v] : e.to);
			dfs_hld(e.to, v, t);
		}
		out[v] = t;
	}
public:
	HLD(Graph& _g, int _root = 0)
		:g(_g), n(g.size()), root(_root), sz(n), par(n, -1), head(n, -1), in(n), out(n), rev(n), dep(n, 0) {
		dfs_sz(root, -1);
		int t = 0;
		head[root] = root;
		dfs_hld(root, -1, t);
	}
	inline int get_in(int a) { return in[a]; }
	inline int get_sz(int a) { return sz[a]; }
	inline int get_rev(int a) { return rev[a]; }
	inline int get_dep(int a) { return dep[a]; }
	int lca(int a, int b) {
		for (;; b = par[head[b]]) {
			if (in[a] > in[b])swap(a, b);
			if (head[a] == head[b])return a;
		}
	}
	P subtree_query(int a) { return { in[a], out[a] }; }
	vector<P> path_query(int a, int b, bool edge = false) {
		vector<P> ret;
		for (;; b = par[head[b]]) {
			if (in[a] > in[b])swap(a, b);
			if (head[a] == head[b])break;
			ret.push_back({ in[head[b]],in[b] + 1 });
		}
		ret.push_back({ in[a] + edge,in[b] + 1 });
		return ret;
	}
};

void solve(){
    ll n,q;
    cin>>n>>q;
    Graph g(n);
    REP(i,n-1){
        ll a,b,c,d;
        cin>>a>>b>>c>>d;
        a--;b--;
        add_edge(g,a,b,d,true,d,c);
    }

    HLD hld(g,0);

    Array d(n,INF);//根からの距離
    auto dfs=[&](auto &&self, int v, int p)->void{
        for(auto e:g[v]){
            if(e.to==p) continue;
            d[e.to]=d[v]+e.cap;
            self(self,e.to,v);
        }
    };
    d[0]=0;
    dfs(dfs, 0, -1);

    vvec<P> c(n);//色ごとの座標と距離
    auto dfs_col=[&](auto &&self, int v, int p)->void{
        for(auto e:g[v]){
            if(e.to==p){
                c[e.col].push_back({hld.get_in(v),e.cap});
                continue;
            }
            self(self,e.to,v);
        }
    };
    dfs_col(dfs_col, 0, -1);

    vvec<ll> csum(n);//色毎の距離の累積和
    REP(i,n){
        sort(all(c[i]));
        csum[i].push_back(0LL);
        REP(j, c[i].size()){
            csum[i].push_back(csum[i][j]+c[i][j].second);
        }
    }

    REP(_,q){
        int x,y,u,v;
        cin>>x>>y>>u>>v;
        u--;v--;
        int root=hld.lca(u,v);
        ll dd=d[u]+d[v]-2*d[root];

        vec<P> ret=hld.path_query(u,v,true);
        for(auto j:ret){
            ll l=j.first;
            ll r=j.second;
            auto s = lower_bound(all(c[x]),make_pair(l,-1LL))-c[x].begin();
            auto t = lower_bound(all(c[x]),make_pair(r,-1LL))-c[x].begin();
            dd -= csum[x][t]-csum[x][s];
            dd += (t-s)*y;
        }
        cout<<dd<<en;
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	
	solve();
	//ll t;cin>>t;REP(i,t) solve();

    return 0;
}


Measured memory_bytes: 29172