#define print(x) printf("%d\n",x)

#include <map>
#include <cstdio>
inline int getInt(){ int s; scanf("%d", &s); return s; }

#include <queue>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

#include <set>

using namespace std;

class Tree{
public:
  vector<vector<int> > next;
  vector<vector<int> > prev2;
  vector<int> depth;
  int root;

  Tree(const vector<vector<int> > &next,
       const vector<vector<int> > &prev2,
       const vector<int> depth,
       const int root) :
    next(next), prev2(prev2),
    depth(depth), root(root){
  }

  int lca(int a, int b) const{
    if(depth[a] > depth[b]) swap(a, b);
    int ddiff = depth[b] - depth[a];

    int dmax = prev2[0].size();
    REP(i,dmax){
      if(ddiff & (1 << i)) b = prev2[b][i];
    }

    if(a == b) return a;

    for(int i = dmax - 1; i >= 0; i--){
      if(prev2[a][i] != prev2[b][i]){
	a = prev2[a][i];
	b = prev2[b][i];
      }
    }

    return prev2[a][0];
  }
};

// g must be tree structure
Tree fromGraph(const vector<vector<int> > &g, int root = 0){
  const int n = g.size();
  vector<vector<int> > next(n);
  vector<vector<int> > prev2(n);
  vector<int> depth(n, -1);

  queue<pair<int, int> > q;

  q.push(make_pair(root, -1));
  depth[root] = 0;
  prev2[root].push_back(root);

  while(q.size()){
    const pair<int, int> d = q.front(); q.pop();
    const int now  = d.first;
    const int prev = d.second;

    REP(i,g[now].size()){
      int next = g[now][i];
      if(next != prev){
	q.push(make_pair(next, now));
	depth[next] = depth[now] + 1;
	prev2[next].push_back(now);
      }
    }
  }

  bool flag = true;
  while(flag){
    const int last = prev2[root].size() - 1;
    flag = false;

    REP(i,n){
      int data = prev2[prev2[i][last]][last];
      prev2[i].push_back(data);
      flag |= data != 0;
    }
  }

  return Tree(next, prev2, depth, root);
}

vector<vector<int> > costs;
vector<vector<int> > graph;
vector<vector<int> > colors;
vector<int> dists;

map<int, int> cnts;
map<int, int> tot;

vector<map<int, int> > memo;
vector<map<int, int> > cmemo;

void dfs(int pos, int prev, int dist){
  dists[pos] = dist;

  for(auto &m : memo[pos]){
    m.second = tot[m.first];
  }
  for(auto &m : cmemo[pos]){
    m.second = cnts[m.first];
  }

  REP(i,graph[pos].size()) if(graph[pos][i] != prev){
    const int next = graph[pos][i];
    tot[colors[pos][i]] += costs[pos][i];
    cnts[colors[pos][i]]++;
    dfs(next, pos, dist + costs[pos][i]);
    tot[colors[pos][i]] -= costs[pos][i];
    cnts[colors[pos][i]]--;
  }
}

int main(){
  const int n = getInt();
  const int q = getInt();

  costs = vector<vector<int> >(n);
  graph = vector<vector<int> >(n);
  colors = vector<vector<int> >(n);
  dists = vector<int>(n);
  memo = vector<map<int, int> >(n);
  cmemo = vector<map<int, int> >(n);

  REP(i,n-1){
    const int a = getInt() - 1;
    const int b = getInt() - 1;
    const int c = getInt();
    const int d = getInt();

    costs[a].push_back(d); costs[b].push_back(d);
    graph[a].push_back(b); graph[b].push_back(a);
    colors[a].push_back(c); colors[b].push_back(c);
  }

  const auto g = fromGraph(graph);

  vector<int> xs(q);
  vector<int> ys(q);
  vector<int> us(q);
  vector<int> vs(q);
  REP(i,q){
    const int x = xs[i] = getInt();
    const int y = ys[i] = getInt();
    const int u = us[i] = getInt() - 1;
    const int v = vs[i] = getInt() - 1;

    memo[u][x] = -1;
    memo[v][x] = -1;
    memo[g.lca(u, v)][x] = -1;
    cmemo[u][x] = -1;
    cmemo[v][x] = -1;
    cmemo[g.lca(u, v)][x] = -1;
  }

  dfs(0, -1, 0);

  REP(i,q){
    const int x = xs[i];
    const int y = ys[i];
    const int u = us[i];
    const int v = vs[i];

    const int lca = g.lca(u, v);
    const int d = dists[u] + dists[v] - 2 * dists[lca];
    const int cd = y * (cmemo[u][x] + cmemo[v][x] - 2 * cmemo[lca][x]) - (memo[u][x] + memo[v][x] - 2 * memo[lca][x]);
    // printf("%d %d %d\n", u, v, lca);
    // printf("%d %d %d\n", cmemo[u][x], cmemo[v][x], cmemo[lca][x]);
    // printf("%d %d %d\n", d, (cmemo[u][x] + cmemo[v][x] - 2 * cmemo[lca][x]), (memo[u][x] + memo[v][x] - 2 * memo[lca][x]));
    printf("%d\n", d + cd);
  }

  return 0;
}

Measured memory_bytes: 75156