#include <bits/stdc++.h>
using namespace std;
#define REP(i, a, n) for (int i = (a); i < (int)(n); i++)
#define rep(i, n) REP(i, 0, n)
#define FOR(it, c) \
  for (__typeof((c).begin()) it = (c).begin(); it != (c).end(); ++it)
#define ALLOF(c) (c).begin(), (c).end()
typedef long long ll;
typedef unsigned long long ull;

class RMQ {
  static const int MAX_N = 1 << 18;
  static const int INF = 999999999;
  int RMQ_n;
  std::vector<std::pair<int, int>> RMQ_dat;

 public:
  RMQ() : RMQ(1 << 18) {}
  RMQ(int n_) : RMQ_dat(2 * MAX_N - 1) {
    RMQ_n = 1;
    while (RMQ_n < n_) RMQ_n *= 2;
    for (int i = 0; i < 2 * RMQ_n - 1; i++)
      RMQ_dat[i] = std::make_pair(INF, INF);
  }
  std::pair<int, int> query(int a, int b) { return _query(a, b, 0, 0, RMQ_n); }
  std::pair<int, int> _query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) return std::make_pair(INF, INF);
    if (a <= l && r <= b)
      return RMQ_dat[k];
    else {
      std::pair<int, int> vl = _query(a, b, k * 2 + 1, l, (l + r) / 2);
      std::pair<int, int> vr = _query(a, b, k * 2 + 2, (l + r) / 2, r);

      if (vl.first < vr.first)
        return vl;
      else
        return vr;
    }
  }
  void update(int i, std::pair<int, int> x) {
    i += RMQ_n - 1;
    RMQ_dat[i] = x;
    while (i > 0) {
      i = (i - 1) / 2;
      if (RMQ_dat[i * 2 + 1].first < RMQ_dat[i * 2 + 2].first) {
        RMQ_dat[i] = RMQ_dat[i * 2 + 1];
      } else {
        RMQ_dat[i] = RMQ_dat[i * 2 + 2];
      }
    }
  }
};

class LabeledTreeDistance {
  struct Edge {
    int src, dst;
    int label;
    int dist;
    int cusum_num;
    int cusum_dist;
  };
  static const int root = 0;
  int N, L;
  std::vector<std::vector<Edge>> edges;

  std::vector<std::vector<std::pair<int, Edge>>> labeled;
  std::vector<Edge> tour;
  std::unordered_map<int, int> v2idx;

  RMQ rmq;

  void dfs(int now, int prev) {
    v2idx[now] = tour.size() - 1;
    for (int i = 0; i < edges[now].size(); i++) {
      if (edges[now][i].dst == prev) continue;
      Edge e = edges[now][i];
      tour.push_back(e);
      dfs(e.dst, now);
      e.src = e.dst;
      e.dst = now;
      e.dist = -e.dist;
      tour.push_back(e);
    }
  }

 public:
  LabeledTreeDistance(int N, int L) : N(N), L(L), edges(N), labeled(L) {}

  void add_edge(int a, int b, int l, int d) {
    edges[a].push_back((Edge){a, b, l, d, 0, 0});
    edges[b].push_back((Edge){b, a, l, d, 0, 0});
  }

  void build() {
    dfs(root, -1);

    int cusum_num = 0, cusum_dist = 0;
    for (int i = 0; i < tour.size(); i++) {
      cusum_num += (tour[i].dist >= 0) ? 1 : -1;
      cusum_dist += tour[i].dist;
      tour[i].cusum_num = cusum_num;
      tour[i].cusum_dist = cusum_dist;
      labeled[tour[i].label].emplace_back(i, tour[i]);
      rmq.update(i, std::make_pair(
                        tour[i].cusum_num,
                        tour[i].cusum_dist >= 0 ? tour[i].dst : tour[i].src));
    }
    for (int i = 0; i < labeled.size(); i++) {
      cusum_num = 0;
      cusum_dist = 0;
      for (int j = 0; j < labeled[i].size(); j++) {
        cusum_num += (labeled[i][j].second.dist >= 0) ? 1 : -1;
        cusum_dist += labeled[i][j].second.dist;
        labeled[i][j].second.cusum_num = cusum_num;
        labeled[i][j].second.cusum_dist = cusum_dist;
      }
    }
  }

  std::pair<int, int> get(int v) {
    if (v == root) return std::make_pair(0, 0);
    int idx = v2idx[v];
    return std::make_pair(tour[idx].cusum_num, tour[idx].cusum_dist);
  }

  std::pair<int, int> get(int label, int v) {
    if (v == root) return std::make_pair(0, 0);
    int idx = v2idx[v];
    if (labeled[label].size() == 0) return std::make_pair(0, 0);
    int lb = -1, ub = labeled[label].size();
    while (ub - lb > 1) {
      int mid = (lb + ub) / 2;
      int lidx = -1;
      if (mid >= 0) lidx = labeled[label][mid].first;
      if (lidx <= idx)
        lb = mid;
      else
        ub = mid;
    }
    if (lb == -1)
      return std::make_pair(0, 0);
    else
      return std::make_pair(labeled[label][lb].second.cusum_num,
                            labeled[label][lb].second.cusum_dist);
  }

  int lca(int a, int b) {
    int aa = v2idx[a];
    int bb = v2idx[b];
    if (aa > bb) {
      std::swap(a, b);
      std::swap(aa, bb);
    }
    if (aa == -1) return root;
    return rmq.query(aa, bb + 1).second;
  }
};

int main() {
  int N, Q;
  cin >> N >> Q;
  vector<vector<int>> v;
  LabeledTreeDistance ltd(N, N - 1);
  rep(i, N - 1) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--;
    b--;
    c--;
    v.push_back({a, b, c, d});
    ltd.add_edge(a, b, c, d);
  }

  ltd.build();

  for (int i = 0; i < Q; i++) {
    int x, y, a, b;
    cin >> x >> y >> a >> b;
    x--;
    a--;
    b--;

    int c = ltd.lca(a, b);

    ll m1 = ltd.get(a).second + ltd.get(b).second - 2LL * ltd.get(c).second;
    ll m2 = ltd.get(x, a).second + ltd.get(x, b).second -
            2LL * ltd.get(x, c).second;
    ll c2 =
        ltd.get(x, a).first + ltd.get(x, b).first - 2LL * ltd.get(x, c).first;

    ll ret = m1 - m2 + c2 * y;

    cout << ret << endl;
  }

  return 0;
}


Measured memory_bytes: 47276