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

// 0-indexed
template <class T>
struct BIT {
  int treesize;
  vector<T> lst;
  // constructor
  BIT(int newn = 0) : treesize(newn), lst(newn + 1, 0) {}
  // a_place += num
  void add(int place, T num) {
    ++place;
    while (place <= treesize) {
      lst[place] += num;
      place += place & -place;
    }
  }
  // sum between [0,place)
  T sum(int place) {
    T res = 0;
    while (place > 0) {
      res += lst[place];
      place -= place & -place;
    }
    return res;
  }
  // sum [l,r)
  T sum(int left, int right) { return sum(right) - sum(left); }
};

struct HeavyLightDecomposition {
  int root;
  vector<vector<int>> g;
  vector<int> sz, par, dep, in, out, head;
  HeavyLightDecomposition(int n = 1, int _root = 0)
      : root(_root), g(n), sz(n), par(n), dep(n), in(n), out(n), head(n) {}
  HeavyLightDecomposition(const vector<vector<int>> &_g, const int _root = 0)
      : root(_root),
        g(_g),
        sz(_g.size()),
        par(_g.size()),
        dep(_g.size()),
        in(_g.size()),
        out(_g.size()),
        head(_g.size()) {
    build();
  }
  void add(int a, int b) {
    g[a].push_back(b);
    g[b].push_back(a);
  }
  void build() {
    dfs_sz(root, -1, 0);
    int t = 0;
    dfs_hld(root, -1, t);
  }
  void dfs_sz(int now, int bf, int d) {
    dep[now] = d;
    par[now] = bf;
    sz[now] = 1;
    if (g[now].size() && g[now][0] == bf) swap(g[now][0], g[now].back());
    for (auto &to : g[now]) {
      if (to == bf) continue;
      dfs_sz(to, now, d + 1);
      sz[now] += sz[to];
      if (sz[g[now][0]] < sz[to]) swap(g[now][0], to);
    }
  }
  void dfs_hld(int now, int bf, int &t) {
    in[now] = t++;
    for (auto &to : g[now]) {
      if (to == bf) continue;
      head[to] = (g[now][0] == to ? head[now] : to);
      dfs_hld(to, now, t);
    }
    out[now] = t;
  }
  int lca(int x, int y) {
    for (;; y = par[head[y]]) {
      if (in[x] > in[y]) swap(x, y);
      if (head[x] == head[y]) return x;
    }
  }
  int chil(int x, int y) { return dep[x] < dep[y] ? y : x; }
  //[l,r)
  template <typename F>
  void for_each(int x, int y, const F &f) {
    for (;; y = par[head[y]]) {
      if (in[x] > in[y]) swap(x, y);
      f(max(in[head[y]], in[x]), in[y] + 1);
      if (head[x] == head[y]) return;
    }
  }
  //[l,r)
  template <typename F>
  void for_eachedge(int x, int y, const F &f) {
    while (1) {
      if (in[x] > in[y]) swap(x, y);
      if (head[x] != head[y]) {
        f(in[head[y]], in[y] + 1);
        y = par[head[y]];
      } else {
        if (x != y) f(in[x] + 1, in[y] + 1);
        break;
      }
    }
  }
  template <typename T, typename F>
  void update(int node, T x, const F &f) {
    f(in[node], x);
    f(out[node], -x);
    // laze pattern
    // f(in[node], out[node], x);
  }
};

struct edge {
  int x, y, col;
  long long dis;
};

struct query {
  int id, x, y;
  long long d;
};

int n, q;

vector<vector<query>> queries;
vector<vector<int>> g, coledges;
vector<edge> edges;
vector<long long> res;
HeavyLightDecomposition hld;
BIT<long long> cnt, sum;

void solve();

int main() {
  cin >> n >> q;
  queries.resize(n);
  g.resize(n);
  coledges.resize(n);
  edges.resize(n - 1);
  res.resize(q);
  for (int i = 0; i < n - 1; ++i) {
    cin >> edges[i].x >> edges[i].y >> edges[i].col >> edges[i].dis;
    --edges[i].x, --edges[i].y, --edges[i].col;
    g[edges[i].x].push_back(edges[i].y);
    g[edges[i].y].push_back(edges[i].x);
    coledges[edges[i].col].push_back(i);
  }
  hld = HeavyLightDecomposition(g);
  cnt = BIT<long long>(2 * n);
  sum = BIT<long long>(2 * n);
  for (int i = 0; i < q; ++i) {
    int x, y, u, v;
    cin >> x >> y >> u >> v;
    queries[x - 1].push_back({i, --u, --v, y});
  }
  solve();
  for (int i = 0; i < q; ++i) cout << res[i] << endl;
  return 0;
}

void solve() {
  auto sumf = [](int l, long long r) { sum.add(l, r); };
  auto cntf = [](int l, long long r) { cnt.add(l, r); };
  // make sum
  for (auto e : edges) hld.update(hld.chil(e.x, e.y), e.dis, sumf);
  for (int i = 0; i < n; ++i) {
    // remove col i edge
    for (int id : coledges[i]) {
      edge &e = edges[id];
      int chil = hld.chil(e.x, e.y);
      hld.update(chil, 1, cntf);
      hld.update(chil, -e.dis, sumf);
    }
    // calc distance
    for (auto qu : queries[i]) {
      int r = hld.lca(qu.x, qu.y);
      long long now = sum.sum(hld.in[r] + 1, hld.in[qu.x] + 1) +
                      sum.sum(hld.in[r] + 1, hld.in[qu.y] + 1);
      now += qu.d * (cnt.sum(hld.in[r] + 1, hld.in[qu.x] + 1) +
                     cnt.sum(hld.in[r] + 1, hld.in[qu.y] + 1));
      res[qu.id] = now;
    }
    // add col i edge
    for (int id : coledges[i]) {
      edge &e = edges[id];
      int chil = hld.chil(e.x, e.y);
      hld.update(chil, -1, cntf);
      hld.update(chil, e.dis, sumf);
    }
  }
}


Measured memory_bytes: 32944