#include<bits/stdc++.h>
using namespace::std;
__attribute__((constructor))void init(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(15);}
#define endl "\n"
using lint =long long;
using ll =long long;
#define rep(i,n) for(lint i=0;i<n;i++)
#define repi(i,a,b) for(lint i=a;i<b;i++)
#define rrep(i,n) for(lint i=n-1;i>=0;i--)
using vec=vector<lint>;
using mat=vector<vec>;
#define MOD 1000000007LL
#define INF (1LL<<60)
#define all(a) (a).begin(),(a).end()
template<typename T>inline bool chmin(T& s,const T& t){bool res=s>t;s=min(s,t);return res;}
template<typename T>inline bool chmax(T& s,const T& t){bool res=s<t;s=max(s,t);return res;}
inline __int128_t gcd(__int128_t A,__int128_t B){return B?gcd(B,A%B):A;}
inline auto lcm(auto A,auto B){return A/gcd(A,B)*B;}
auto call=[](auto f,auto... args){return f(f,args...);};

template<typename T>
class pvector{
    struct node;
    using np=node*;
    struct node{
        T data;
        np ch[16];
        node(){
            for(int i=0;i<16;i++)ch[i]=nullptr;
        }
    };
    np root=nullptr;
    np set(int idx,T val,np t){
        np res=t?new node(*t):new node();
        if(idx==0)res->data=val;
        else res->ch[idx&15]=set(idx>>4,val,res->ch[idx&15]);        
        return res;
    }
    T get(int idx,np t){
        if(!t)return T();
        return idx?get(idx>>4,t->ch[idx&15]):t->data;
    }
    public:
    pvector(){}
    pvector(np t):root(t){}
    pvector set(int idx,T val){
        return pvector(set(idx,val,root));
    }
    T get(int idx){
        return get(idx,root);
    }
};

template<typename T>
class HLD_seg{
	class segment{
		T* node;
		int n=1;
		public:
		segment(int sz){
			while(n<sz)n<<=1;
			node=new T[(n<<1)-1];
			for(int i=0;i<(n<<1)-1;i++)node[i]=e;
		}
		segment(const vector<T>& v){
			while(n<(int)v.size())n<<=1;
			node=new T[(n<<1)-1];
			for(int i=0;i<(int)v.size();i++)node[i+n-1]=v[i];
        	for(int i=n-2;i>=0;i--)node[i]=f(node[(i<<1)+1],node[(i<<1)+2]);
		}
		T get(auto l,auto r){
			if(l>r)swap(l,r);
			l+=n;r+=n+1;
			T s=e;
			while(l<r){
				if(l&1)s=f(s,node[l++-1]);
				if(r&1)s=f(s,node[--r-1]);
				l>>=1;r>>=1;
			}
			return s;
		}
		void update(auto t,T val){
			t+=n-1;
			while(1){
				node[t]=f(node[t],val);
				t=(t-1)>>1;
				if(!t)break;
			}
		}
	};
	int child_size(const auto& v,int n,int p){
		int cnt=0;
		for(auto t:v[n]){
			if(t!=p)cnt+=child_size(v,t,n);
		}
		return sz[n]=cnt+1;
	}
	void make_hld(const auto&v,int n,int p){
		static int idx=0;
		vertex[n]=idx++;
		int mx=0,heavy=-1;
		for(auto t:v[n])if(t!=p&&mx<sz[t]){
			mx=sz[t];
			heavy=t;
		}
		if(heavy!=-1){
			par[heavy]=par[n];
			head[heavy]=head[n];
			make_hld(v,heavy,n);
		}
		for(auto t:v[n]){
			if(t!=heavy&&t!=p){
				par[t]=n;
				head[t]=t;
				make_hld(v,t,n);
			}
		}
	}
	int* sz;
	int* vertex;
	int* par;
	int* head;
	segment* seg;
	public:
	HLD_seg(const auto& v,int root=0){
		make(v,root);
		seg=new segment(v.size());
	}
	HLD_seg(const auto& v,const auto& a,int root=0){
		make(v,root);
		vector<T>tmp(v.size());
		for(int i=0;i<(int)v.size();i++){
			tmp[vertex[i]]=a[i];
		}
		seg=new segment(tmp);
	}
	void make(const auto& v,int root){
		sz=new int[v.size()];
		vertex=new int[v.size()];
		par=new int[v.size()];
		head=new int[v.size()];
		child_size(v,root,-1);
		par[root]=root;
		head[root]=root;
		make_hld(v,root,-1);
	}
	int lca(auto l,auto r){
		while(head[l]!=head[r]){
			if(sz[head[l]]>sz[head[r]])r=par[r];
			else l=par[l];
		}
		return sz[l]>sz[r]?l:r;
	}
	inline void update(auto t,T x){
		seg->update(vertex[t],x);
	}
	T get(auto u,auto v){
		T res=e;
		while(head[u]!=head[v]){
			if(sz[head[u]]>sz[head[v]]){
				res=f(res,seg->get(vertex[v],vertex[head[v]]));
				v=par[v];
			}
			else{
				res=f(res,seg->get(vertex[u],vertex[head[u]]));
				u=par[u];
			}
		}
		return f(res,seg->get(vertex[u],vertex[v]));
	}
	inline T get_subtree(auto u){
		return seg->get(vertex[u],vertex[u]+sz[u]-1);
	}
	protected:
	constexpr static T e=0;
	constexpr static
	T f(const T& s,const T& t){
		return s+t;
	}
};

lint n,q;
vector<pvector<lint>>v;
vector<pvector<lint>>cnt;
vector<vector<tuple<lint,lint,lint>>>l;
vector<vector<lint>>g;
vector<lint>su;
void f(lint p,lint k){
    for(auto data:l[k]){
        lint t,c,d;
        tie(t,c,d)=data;
        if(t==p)continue;
        else{
            su[t]=su[k]+d;
            v[t]=v[k].set(c,v[k].get(c)+d);
            cnt[t]=cnt[k].set(c,cnt[k].get(c)+1);
            f(k,t);
        }
    }
}
int main(){
    cin>>n>>q;
    v.resize(n);cnt.resize(n);l.resize(n);g.resize(n);su.resize(n,0);
    rep(i,n-1){
        lint a,b,c,d;
        cin>>a>>b>>c>>d;
        a--;b--;c--;
        l[a].emplace_back(b,c,d);
        l[b].emplace_back(a,c,d);
        g[a].emplace_back(b);
        g[b].emplace_back(a);
    }
    f(-1,0);
    HLD_seg<lint>lca(g);
    rep(i,q){
        lint c,d,s,t;
        cin>>c>>d>>s>>t;
        c--;s--;t--;
        lint u=lca.lca(s,t);
        lint sv=su[s]+cnt[s].get(c)*d-v[s].get(c);
        lint tv=su[t]+cnt[t].get(c)*d-v[t].get(c);
        lint uv=su[u]+cnt[u].get(c)*d-v[u].get(c);
        cout<<sv+tv-2*uv<<endl;
    }
}


Measured memory_bytes: 190128