#include <bits/stdc++.h>

using namespace std;
using ll = long long;

class EulerTourForEdge {
private:
  vector<int> ds, us, dep;
  int pos;

  void dfs(int v, int p, int d) {
    dep[v] = d;
    for (int u : G[v]) {
      if (u == p)
        continue;
      ds[u] = pos++;
      dfs(u, v, d + 1);
      us[u] = pos++;
    }
  }

public:
  vector<vector<int>> G;

  EulerTourForEdge() {}
  EulerTourForEdge(int n) : ds(n), us(n), dep(n), G(n) {}

  void add_edge(int u, int v) {
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  void build(int r = 0) {
    pos = 0;
    dfs(r, -1, 0);
  }

  int child(int u, int v) { return dep[u] < dep[v] ? v : u; }

  template <typename T, typename F>
  T query(int v, F f) {
    return f(0, us[v]);
  }

  template <typename T, typename F>
  T query(int u, int v, F f) {
    if (dep[u] < dep[v])
      swap(u, v);
    return query<T>(u, f) - query<T>(v, f);
  }

  template <typename T, typename G>
  void update(int v, T x, G g) {
    g(ds[v], +x);
    g(us[v], -x);
  }
};

struct LCA {
  const int lg = 12;
  const int sz = 1 << lg;
  const int ms = sz - 1;
  int n;
  vector<int> P, D, E, A, B, T, ht;
  vector<vector<int>> G, dat;
  LCA(int n)
      : n(n),
        P(n, -1),
        D(n),
        E(n * 2, 0),
        A(n * 2, -1),
        B(n * 2 / lg + 1),
        T(sz, 0),
        G(n) {}

  void add_edge(int u, int v) {
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  void dfs(int v, int p, int d, int &k) {
    D[v] = k;
    A[k] = P[v] = p;
    E[k++] = d;
    for (int u : G[v])
      if (u != p)
        dfs(u, v, d + 1, k);
    A[k] = P[v];
    E[k++] = d - 1;
  }

  // if it need leftmost, then add: if(E[i]==E[j]) return i<j?i:j;
  inline int comp(int i, int j) { return E[i] < E[j] ? i : j; };
  inline int comp(int i, int j, int k) { return comp(comp(i, j), k); };

  void build(int r = 0) {
    int k = 0;
    dfs(r, -1, 1, k);

    B[0] = 1;
    for (int i = 1; i < n * 2; i++)
      B[i / lg] |= (E[i - 1] < E[i]) << (i % lg);

    for (int b = 0; b < sz; b++) {
      int e = 0, w = 1, &x = T[b];
      for (int i = 0; i < lg; i++) {
        if ((b >> i) & 1)
          e++;
        else
          e--;
        if (e < w)
          e = w, x = i;
      }
    }

    int m = (n * 2 + lg - 1) / lg;
    int h = 1;
    while ((1 << h) < m)
      h++;
    dat.assign(h, vector<int>(m, -1));
    ht.assign(m + 1, 0);
    for (int j = 2; j <= m; j++)
      ht[j] = ht[j >> 1] + 1;

    for (int j = 0; j < n * 2; j++) {
      if (dat[0][j / lg] < 0)
        dat[0][j / lg] = j;
      dat[0][j / lg] = comp(dat[0][j / lg], j);
    }

    for (int i = 1, p = 1; i < h; i++, p <<= 1)
      for (int j = 0; j < m; j++)
        dat[i][j] = comp(dat[i - 1][j], dat[i - 1][min(j + p, m - 1)]);
  }

  inline int cs(int a, int b) {
    int l = b - a;
    return comp(dat[ht[l]][a], dat[ht[l]][b - (1 << ht[l])]);
  }

  inline int es(int i, int l, int r) {
    int x = r - i * lg + 1, y = l - i * lg;
    int b = (((B[i] | (ms << x)) >> y) | (ms << (lg - y))) & ms;
    return l + T[b];
  }

  inline int ls(int i, int l) {
    int k = l - i * lg;
    int b = ((B[i] >> k) | (ms << (lg - k))) & ms;
    return l + T[b];
  }

  inline int rs(int j, int r) {
    int k = r - j * lg + 1;
    int b = (B[j] | (ms << k)) & ms;
    return j * lg + T[b];
  }

  inline int rmq(int l, int r) {
    int i = l / lg, j = r / lg;
    if (i == j)
      return es(i, l, r);
    if (i + 1 == j)
      return comp(ls(i, l), rs(j, r));
    return comp(ls(i, l), cs(i + 1, j), rs(j, r));
  }

  int lca(int l, int r) {
    if (l == r)
      return l;
    if (D[l] > D[r])
      swap(l, r);
    int x = D[l], y = D[r];
    int m = rmq(x, y);
    return m == x ? l : A[m];
  }
};

template <typename T>
struct SegmentTree {
  using F = function<T(T, T)>;
  int n;
  F f;
  T ti;
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(F f, T ti) : f(f), ti(ti) {}
  void init(int n_) {
    n = 1;
    while (n < n_)
      n <<= 1;
    dat.assign(n << 1, ti);
  }
  void build(const vector<T> &v) {
    int n_ = v.size();
    init(n_);
    for (int i = 0; i < n_; i++)
      dat[n + i] = v[i];
    for (int i = n - 1; i; i--)
      dat[i] = f(dat[(i << 1) | 0], dat[(i << 1) | 1]);
  }
  void set_val(int k, T x) {
    dat[k += n] = x;
    while (k >>= 1)
      dat[k] = f(dat[(k << 1) | 0], dat[(k << 1) | 1]);
  }
  T query(int a, int b) {
    T vl = ti, vr = ti;
    for (int l = a + n, r = b + n; l < r; l >>= 1, r >>= 1) {
      if (l & 1)
        vl = f(vl, dat[l++]);
      if (r & 1)
        vr = f(dat[--r], vr);
    }
    return f(vl, vr);
  }
  template <typename C>
  int find(int st, C &check, T &acc, int k, int l, int r) {
    if (l + 1 == r) {
      acc = f(acc, dat[k]);
      return check(acc) ? k - n : -1;
    }
    int m = (l + r) >> 1;
    if (m <= st)
      return find(st, check, acc, (k << 1) | 1, m, r);
    if (st <= l && !check(f(acc, dat[k]))) {
      acc = f(acc, dat[k]);
      return -1;
    }
    int vl = find(st, check, acc, (k << 1) | 0, l, m);
    if (~vl)
      return vl;
    return find(st, check, acc, (k << 1) | 1, m, r);
  }
  template <typename C>
  int find(int st, C &check) {
    T acc = ti;
    return find(st, check, acc, 1, 0, n);
  }
};

int main() {
  ll N, Q;
  cin >> N >> Q;
  LCA lca = LCA(N);
  EulerTourForEdge et(N);
  vector<ll> aa(N), bb(N), cc(N), dd(N), xx(Q), yy(Q), uu(Q), vv(Q);
  vector<vector<ll>> C(N), D(N);
  for (int i = 1; i < N; ++i) {
    cin >> aa[i] >> bb[i] >> cc[i] >> dd[i];
    aa[i]--;
    bb[i]--;
    lca.add_edge(aa[i], bb[i]);
    et.add_edge(aa[i], bb[i]);
    C[cc[i]].push_back(i);
  }
  et.build();
  lca.build();

  for (int i = 0; i < Q; i++) {
    cin >> xx[i] >> yy[i] >> uu[i] >> vv[i];
    uu[i]--;
    vv[i]--;
    D[xx[i]].emplace_back(i);
  }

  auto f = [&](ll a, ll b) { return a + b; };
  SegmentTree<ll> cnt(f, 0);
  SegmentTree<ll> sum(f, 0);
  cnt.build(vector<ll>(N * 2, 0));
  sum.build(vector<ll>(N * 2, 0));

  for (int i = 1; i < N; i++) {
    ll child = et.child(aa[i], bb[i]);
    auto g = [&](ll v, ll d) { sum.set_val(v, d); };
    et.update(child, dd[i], g);
  }

  vector<ll> ret(Q, 0);
  for (int i = 0; i < Q; i++) {
    ll r = lca.lca(uu[i], vv[i]);
    auto f = [&](ll l, ll r) { return sum.query(l, r); };
    ret[i] += et.query<ll>(r, uu[i], f);
    ret[i] += et.query<ll>(r, vv[i], f);
  }
  sum.build(vector<ll>(N * 2, 0));

  for (int t = 1; t < N; t++) {
    for (auto i : C[t]) {
      ll child = et.child(aa[i], bb[i]);

      auto g1 = [&](ll v, ll d) { cnt.set_val(v, d); };
      auto g2 = [&](ll v, ll d) { sum.set_val(v, d); };
      et.update(child, 1, g1);
      et.update(child, dd[i], g2);
    }

    for (auto i : D[t]) {
      ll res = 0, num = 0;
      ll r = lca.lca(uu[i], vv[i]);
      auto f1 = [&](ll l, ll r) { return cnt.query(l, r); };
      auto f2 = [&](ll l, ll r) { return sum.query(l, r); };
      num += et.query<ll>(r, uu[i], f1);
      num += et.query<ll>(r, vv[i], f1);
      res += et.query<ll>(r, uu[i], f2);
      res += et.query<ll>(r, vv[i], f2);
      ret[i] += num * yy[i];
      ret[i] -= res;
    }

    for (auto i : C[t]) {
      ll ch = et.child(aa[i], bb[i]);
      auto g1 = [&](int v, int d) { cnt.set_val(v, d); };
      auto g2 = [&](int v, int d) { sum.set_val(v, d); };
      et.update(ch, 0, g1);
      et.update(ch, 0, g2);
    }
  }

  for (int i = 0; i < Q; i++)
    cout << ret[i] << endl;
}


Measured memory_bytes: 44124