#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"

using namespace std;
using namespace __gnu_pbds;

template <typename T> using order_set = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;

#define ll         long long int
#define endl       '\n'
#define pii        pair <int, ll>
#define mk         make_pair

static const int maxn = 2e5 + 5;
static const int Max  = 2e6 + 6;
static const int logn = 19;

struct Node {
      int st;
      ll sum;
      int lchild, rchild;
      Node(int st = 0, ll sum = 0, int lchild = 0, int rchild = 0)
            : st(st), sum(sum), lchild(lchild), rchild(rchild) {}
} Tree[Max];

int version[maxn];
int NODES;
int N = 100000;

int update(int root, int a, int b, int pos, ll val) {
      int newNode = ++NODES;
      Tree[newNode] = Tree[root];
      if (a == b) {
            Tree[newNode].st += 1;
            Tree[newNode].sum += val;
            return newNode;
      }
      int mid = (a + b) / 2;
      if (pos <= mid) {
            Tree[newNode].lchild = update(Tree[newNode].lchild, a, mid, pos, val);
      }
      else {
            Tree[newNode].rchild = update(Tree[newNode].rchild, mid + 1, b, pos, val);
      }
      Tree[newNode].st = Tree[ Tree[newNode].lchild ].st + Tree[ Tree[newNode].rchild ].st;
      Tree[newNode].sum = Tree[ Tree[newNode].lchild ].sum + Tree[ Tree[newNode].rchild ].sum;
      return newNode;
}

pii query(int proot, int root, int a, int b, int i, int j) {
      if (a > j or b < i) {
            return mk(0, 0);
      }
      if (a >= i and b <= j) {
            return mk(Tree[root].st - Tree[proot].st, Tree[root].sum - Tree[proot].sum);
      }
      int mid = (a + b) / 2;
      pii p = query(Tree[proot].lchild, Tree[root].lchild, a, mid, i, j);
      pii q = query(Tree[proot].rchild, Tree[root].rchild, mid + 1, b, i, j);
      pii res;
      res.first = p.first + q.first;
      res.second = p.second + q.second;
      return res;
}

void init() {
      NODES = 0;
      version[0] = 0;
      for (int i = 0; i < Max; i++) {
            Tree[i] = Node();
      }
}

struct MyNode {
      int v, color, dist;
      MyNode(int v = 0, int color = 0, int dist = 0)
            : v(v), color(color), dist(dist) {}
};

vector < vector <MyNode> > graph;
ll cumdist[maxn];
int depth[maxn];
int father[maxn][logn];

void dfs(int u, int p, int lvl) {
      depth[u] = lvl;
      father[u][0] = p;
      for (int i = 1; i < logn; i++) {
            father[u][i] = father[ father[u][i - 1] ][i - 1];
      }
      for (MyNode it : graph[u]) {
            int v = it.v;
            int color = it.color;
            int dist = it.dist;
            if (v == p) {
                  continue;
            }
            cumdist[v] = cumdist[u] + dist;
            version[v] = update(version[u], 1, N, color, dist);
            dfs(v, u, lvl + 1);
      }
}

int find_lca(int u, int v) {
      if (depth[u] < depth[v]) {
            swap(u, v);
      }
      for (int i = logn - 1; i >= 0; i--) {
            if (depth[ father[u][i] ] >= depth[v]) {
                  u = father[u][i];
            }
      }
      if (u == v) {
            return u;
      }
      for (int i = logn - 1; i >= 0; i--) {
            if (father[u][i] != father[v][i]) {
                  u = father[u][i];
                  v = father[v][i];
            }
      }
      return father[u][0];
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);

      int n, q;
      cin >> n >> q;
      graph.resize(n + 1);
      for (int e = 1; e < n; e++) {
            int u, v, c, d;
            cin >> u >> v >> c >> d;
            graph[u].emplace_back(v, c, d);
            graph[v].emplace_back(u, c, d);
      }
      init();
      dfs(1, 0, 1);
      while (q--) {
            int x, y, u, v;
            cin >> x >> y >> u >> v;
            int lca = find_lca(u, v);
            ll dist = cumdist[u] + cumdist[v] - 2 * cumdist[lca];
            pii p = query(version[lca], version[u], 1, N, x, x);
            pii q = query(version[lca], version[v], 1, N, x, x);
            int cntx = p.first + q.first;
            ll val = p.second + q.second;
            dist = dist - val + cntx * y;
            cout << dist << endl;
      }
}


Measured memory_bytes: 69632