#include <bits/stdc++.h>

#define mp make_pair
#define fst first
#define snd second
#define forn(i,n) for (int i = 0; i < int(n); i++)
#define forn1(i,n) for (int i = 1; i <= int(n); i++)
#define popcnt __builtin_popcount

using namespace std;

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,int> pli;
typedef pair<int,ll> pil;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;

template <typename T> T id(T b) {return b;};
template <class It> bool all(It f,It l){return std::all_of(f,l,id<bool>);}
template <class It> bool any(It f,It l){return std::any_of(f,l,id<bool>);}
template <typename T> void chmax(T &x, T y) {if (x < y) x = y;}
template <typename T> void chmin(T &x, T y) {if (x > y) x = y;}

class lca {
  int n;
  static const int m = 32;
  bool ok = false;
  vector<vector<int>> g;
  vector<vector<int>> par;
  vector<int> depth;
  vector<bool> root;

  void dfs(int u, int p, int d) {
    par[0][u] = p;
    depth[u] = d;
    for (int v : g[u]) {
      if (v != p) dfs(v, u, d+1);
    }
  }

  void init() {
    if (ok) return;
    for (int r = 0; r < n; r++)
      if (root[r]) dfs(r, -1, 0);
    for (int k = 0; k+1 < m; k++) {
      for (int u = 0; u < n; u++) {
        if (par[k][u] < 0) par[k+1][u] = -1;
        else par[k+1][u] = par[k][par[k][u]];
      }
    }
    ok = true;
  }

public:
  lca(int n):n(n) {
    g.resize(n);
    par.assign(m, vector<int>(n));
    depth.resize(n);
    root.assign(n,true);
  }

  void add_edge(int u, int v) {
    g[u].push_back(v);
    root[v] = false;
    ok = false;
  }

  int operator()(int u, int v) {
    init();
    if (depth[u] > depth[v]) swap(u,v);
    for (int k = 0; k < m; k++) {
      if ((depth[v] - depth[u]) >> k & 1) v = par[k][v];
    }
    if (u == v) return u;
    for (int k = m-1; k >= 0; k--) {
      if (par[k][u] != par[k][v]) {
        u = par[k][u]; v = par[k][v];
      }
    }
    return par[0][u];
  }
};

struct edge { int to, col, d; };
enum node_type { U, V, LCA };
typedef pair<int,node_type> node_query; // index(query),node_type

const int MAX_N = 100000, MAX_Q = 100000;
int n,q;
vector<edge> g[MAX_N];
pii query[MAX_N];
vector<node_query> nq[MAX_N];
int dist[MAX_N];
int ans[MAX_Q];
int num[MAX_N];
int sum[MAX_N];

void calc_dist(int u, int d, int p = -1) {
  dist[u] = d;
  for (edge e : g[u]) {
    if (p == e.to) continue;
    calc_dist(e.to,d+e.d,u);
  }
}

void calc_ans(int u, int p = -1) {
  for (node_query q : nq[u]) {
    int col,y;
    tie(col,y) = query[q.fst];
    int c = num[col], s = sum[col];
    int x = -s+c*y;
    if (q.snd == LCA) {
      ans[q.fst] -= 2*x;
    } else {
      ans[q.fst] += x;
    }
  }

  for (edge e : g[u]) {
    if (p == e.to) continue;
    sum[e.col] += e.d;
    num[e.col]++;
    calc_ans(e.to,u);
    sum[e.col] -= e.d;
    num[e.col]--;
  }
}

void make_lca(lca &l, int u, int p = -1) {
  for (edge e : g[u]) {
    if (e.to == p) continue;
    l.add_edge(u, e.to);
    make_lca(l,e.to,u);
  }
}

int main()
{
#ifdef FASTIO
  ios_base::sync_with_stdio(false); cin.tie(nullptr);
#endif

  cin >> n >> q;

  lca l(n);

  forn(i,n-1) {
    int a,b,c,d; cin >> a >> b >> c >> d;
    a--,b--;
    g[a].push_back({b,c,d});
    g[b].push_back({a,c,d});
  }

  calc_dist(0,0);
  make_lca(l,0);

  forn(i,q) {
    int x,y,u,v; cin >> x >> y >> u >> v;
    u--,v--;
    query[i] = mp(x,y);
    nq[u].push_back(mp(i,U));
    nq[v].push_back(mp(i,V));
    int c = l(u,v);
    nq[c].push_back(mp(i,LCA));
    ans[i] = dist[u]+dist[v]-2*dist[c];
  }

  calc_ans(0);

  forn(i,q)
    cout << ans[i] << "\n";

  return 0;
}


Measured memory_bytes: 41720