#define _USE_MATH_DEFINES
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>
#include <functional>
#include <random>
#include <ctime>

using namespace std;

#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

typedef long long int64;
typedef pair<int, int> ii;
const int INF = 1 << 29;
const int MOD = 1e9 + 7;

const int N = 1e5 + 10;
struct Edge {
  int v, w, c;
};

int t[N];
vector<Edge> a[N];
int son[N], f[N], dep[N], sz[N], top[N];
int idx[N], tin[N];
int color[N], len[N];

void DFS(int u, int parent, int dist) {
  len[u] = dist;
  f[u] = parent;
  dep[u] = f[u] < 0 ? 0 : dep[f[u]] + 1;
  sz[u] = 1;
  son[u] = -1;
  for (auto& it : a[u]) {
    int v = it.v;
    if (v == f[u]) continue;
    color[v] = it.c;
    DFS(v, u, dist + it.w);
    sz[u] += sz[v];
    if (son[u] < 0 || sz[son[u]] < sz[v]) {
      son[u] = v;
    }
  }
}

int stamp;
void DFS2(int u, bool heavy) {
  tin[stamp] = u;
  idx[u] = stamp++;
  top[u] = heavy ? top[f[u]] : u;
  if (son[u] >= 0) DFS2(son[u], true);
  for (auto& it : a[u]) {
    int v = it.v;
    if (v == f[u] || v == son[u]) continue;
    DFS2(v, false);
  }
}

void add(ii& x, ii y) {
  x.first += y.first;
  x.second += y.second;
}

struct Node {
  int a, b;
  Node *left, *right;
  map<int, ii> cnt;
  void pushup() {
    cnt = left->cnt;
    for (auto& it : right->cnt) {
      add(cnt[it.first], it.second);
    }
  }
};

Node pool[N << 1], *last = pool;
Node* new_node(int a, int b) {
  Node* cur = last++;
  cur->a = a;
  cur->b = b;
  cur->left = cur->right = nullptr;
  cur->cnt.clear();
  return cur;
}

Node* build(int a, int b) {
  Node* cur = new_node(a, b);
  if (a + 1 == b) {
    int u = tin[a];
    cur->cnt[color[u]] = {1, f[u] < 0 ? 0 : len[u] - len[f[u]]};
    return cur;
  }
  cur->left = build(a, (a + b) / 2);
  cur->right = build((a + b) / 2, b);
  cur->pushup();
  return cur;
}

int A, B, C;
ii query(Node* cur) {
  if (cur->a >= A && cur->b <= B) {
    return cur->cnt.count(C) ? cur->cnt[C] : ii{0, 0};
  }
  ii ret = {0, 0};
  if ((cur->a + cur->b) / 2 > A) add(ret, query(cur->left));
  if ((cur->a + cur->b) / 2 < B) add(ret, query(cur->right));
  return ret;
}

Node* root;
ii walk(int x, int y, int& dist) {
  // cout << "x&y: " << x << " " << y << endl;
  ii ret = {0, 0};
  dist = 0;
  while (true) {
    int fx = top[x], fy = top[y];
    // trace(x, y, fx, fy);
    if (fx == fy) break;
    if (dep[fx] < dep[fy]) {
      A = idx[fy]; B = idx[y] + 1;
      add(ret, query(root));
      dist += len[y] - len[f[fy]];
      y = f[fy];
    } else {
      A = idx[fx]; B = idx[x] + 1;
      add(ret, query(root));
      dist += len[x] - len[f[fx]];
      x = f[fx];
    }
  }
  if (dep[x] > dep[y]) swap(x, y);
  // trace(x, y, idx[x], idx[y]);
  A = idx[x] + 1; B = idx[y] + 1;
  add(ret, query(root));
  dist += len[y] - len[x];
  return ret;
}

int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 1; i < n; ++i) {
    int x, y, w, c;
    scanf("%d%d%d%d", &x, &y, &c, &w);
    --x; --y;
    a[x].push_back({y, w, c});
    a[y].push_back({x, w, c});
  }

  DFS(0, -1, 0);
  stamp = 0;
  DFS2(0, false);
  // for (int i = 0; i < n; ++i) {
  //   trace(i, len[i], dep[i], color[i]);
  // }

  last = pool;
  root = build(0, n);

  while (m--) {
    int c, d, x, y;
    scanf("%d%d%d%d", &c, &d, &x, &y);
    --x; --y;
    C = c;
    int ret;
    auto cur = walk(x, y, ret);
    // trace(x, y, ret);
    ret = ret - cur.second + cur.first * d;
    printf("%d\n", ret);
  }

  return 0;
}


Measured memory_bytes: 102584