#include<bits/stdc++.h>
#define ff first
#define ss second
#define pb push_back
#define pf push_front
#define eb emplace_back
#define emp emplace
#define ins insert
#define mp make_pair
#define mt make_tuple
#define sz(s) (int)s.size()
#define forp(i,a,b) for( int i=a;i<=b;i++)
#define rep(i,n)    for( int i=0;i<n;i++)
#define ren(i,n)    for( int i=n-1;i>=0;i--)
#define forn(i,a,b) for( int i=a;i>=b;i--)
#define w(t) while(t)
#define sc(a) scanf("%d", &a);
#define on cout<<"\n"
#define os cout <<" "
#define o2(a,b) cout<<a<<" "<<b
#define o(a) cout << a
#define ppr(a) cout << a.first << " " << a.second
#define bitcount __builtin_popcount
#define gcd __gcd
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(), v.rend()
#define mem(n,m) memset(n,m,sizeof(n))
#define pii pair<int,int>
#define tiii tuple<int, int, int>
#define pll pair<long long,long long>
#define sii set<int>
#define sll set<long long>
#define vii vector<int>
#define vll vector<long long>
#define mii map<int,int>
#define mll map<long long, long long>
#define lob lower_bound
#define upb upper_bound
#define ret return
#define present(s,x) (s.find(x) != s.end())
#define cpresent(s,x) (find(all(s),x) != s.end())
#define ford(container, it) for(auto it = container.begin(); it != container.end(); it++)
#define fors(container, it, a, b) for(auto it = a; it != b; it++)
#define boost ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define MOD 1000000007
#define EPSILON 1e-9
#define PI acos(-1)
#define int long long
#define inf 1e15
#define debug(a) cerr<<#a<<": ";for(auto i:a)cerr<<i<<" ";cerr<<'\n';
#define trace(a) cerr<<#a<<": "<<a<<"\n"
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>


typedef long long  ll;
typedef long double  ldo;
typedef double  db ;
using namespace std;
auto start = std::chrono::system_clock::now();
inline void skj()
{
  std::chrono::time_point<std::chrono::system_clock> end;
  end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end - start;
  std::time_t end_time = std::chrono::system_clock::to_time_t(end);
  cerr<<"Time taken " << elapsed_seconds.count()*1000<<"\n";
}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
//uniform_int_distribution<int> ud(1, 100); use this for random number generator

    //custom hash for unordered map
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};
inline int binexp(int a,int b,int m)
{
    if(a == 0) {
        ret 0;
    }
    int res=1;
    a%=m;
    while(b)
    {
        if(b&1)
            res=(res*1ll*a)%m;
        a=(a*1ll*a)%m;
        b>>=1;
    }
    return res;
}
inline int binmul(int a, int b, int m) {
    a %= m;
    int res = 0;
    w(b) {
        if(b & 1) {
            res = (res + a) % m;
        }
        a = (a + a) % m;
        b >>= 1;
    }
    ret res;
}
const int N = 1e5+5, logN = 18;
vii g[N];
vii cost[N];
vii col[N];
int level[N], dis[N], c1[N], c2[N], dp[N][logN], n;
unordered_map<int, int> M1[N], M2[N];
vii Qr[N];
inline void dfs(int s, int p) {
    for(int it = 0; it < sz(g[s]); ++it) {
        int i = g[s][it];
        if(i != p) {
            dp[i][0] = s;
            level[i] = 1 + level[s];
            dis[i] = cost[s][it] + dis[s];
            dfs(i, s);
        }
    }
}
int c = 0;
inline void dfs1(int s, int p) {
    for(int i : Qr[s]) {
        M1[s][i] = c1[i];
        M2[s][i] = c2[i];
    }
    for(int i = 0; i < sz(g[s]); ++i) {
        int it = g[s][i];
        if(it != p) {
            c1[col[s][i]]++;
            c2[col[s][i]] += cost[s][i];
            dfs1(it, s);
            c1[col[s][i]]--;
            c2[col[s][i]] -= cost[s][i];
        }
    }
}
void preprocess()
{
	dp[1][0]=1;
	for(int i=1;i<logN;i++)
	{
		for(int j=1;j<=n;j++)
		{
			dp[j][i]=dp[dp[j][i-1]][i-1];
		}
	}
}
int lca(int a,int b)
{
	if(level[a]>level[b])
		swap(a,b);
	int d=level[b]-level[a];
	for(int i=0;i<logN;i++)
	{
		if(d&(1LL<<i))
			b=dp[b][i];
	}
	if(a==b)
		return a;
	for(int i=logN-1;i>=0;i--)
	{
		if(dp[a][i]!=dp[b][i])
			a=dp[a][i],b=dp[b][i];
	}
	return dp[a][0];
}
inline void solve_me_senpai() {
    int q;
    cin >> n >> q;
    rep(i, n - 1) {
        int u, v, c, d;
        cin >> u >> v >> c >> d;
        g[u].pb(v);
        g[v].pb(u);
        col[u].pb(c);
        col[v].pb(c);
        cost[u].pb(d);
        cost[v].pb(d);
    }
    dfs(1, 0);
    preprocess();
    //cout << lca(3, 4) << "\n";
    vector<pair<pii, pii>> qr(q);
    rep(i, q) {
        cin >> qr[i].ff.ff >> qr[i].ff.ss >> qr[i].ss.ff >> qr[i].ss.ss;
        int l = lca(qr[i].ss.ff, qr[i].ss.ss);
        Qr[qr[i].ss.ff].pb(qr[i].ff.ff);
        Qr[qr[i].ss.ss].pb(qr[i].ff.ff);
        Qr[l].pb(qr[i].ff.ff);
        //cout << qr[i].ss.ff << " " << qr[i].ff.ff << " " << l << "\n";
    }
    dfs1(1, 0);
    rep(i, q) {
        int x, y, u, v;
        x = qr[i].ff.ff, y = qr[i].ff.ss, u = qr[i].ss.ff, v = qr[i].ss.ss;
        int l = lca(u, v);
        int dist = dis[u] + dis[v] - 2 * dis[l];
        dist += (M1[u][x] - M1[l][x]) * y + (M1[v][x] - M1[l][x]) * y - (M2[u][x] + M2[v][x] - 2 * M2[l][x]); 
        o(dist);on;
    }
}
int32_t main()
{
    boost
    int t = 1;
    //cin >> t;
    int a = 1;
    while(t--) {
        //cout << "Case #" << a  << ": ";
        solve_me_senpai();
        a++;
    }
    //skj();
    return 0;
}

Measured memory_bytes: 81508