#include <iostream>
#include <fstream>
#include <cmath>
#include <list>
#include <vector>
#include <tuple>
using namespace std;
//#define FILENAME "./F/in/b04"
#define rep(i,n) for(int i=0;i<n;i++)
#define ll long long

#define MOD 1000000007

typedef struct _edge{
  int from;
  int to;
  int color;
  int dist;

  _edge(int _from, int _to, int c, int d) {
    from = _from;
    to = _to;
    color = c;
    dist = d;
  }
  _edge() = default;
}edge;

typedef struct _quiz {
  int x;
  int y;
  int u;
  int v;
  int par;
  int ans;

  _quiz(int _x, int _y, int _u, int _v, int _par) {
    x = _x;
    y = _y;
    u = _u;
    v = _v;
    par = _par;
  }
  void init(int _x, int _y, int _u, int _v, int _par) {
    x = _x;
    y = _y;
    u = _u;
    v = _v;
    par = _par;
  }
  _quiz() = default;
}quiz;



int n,q,a,b,c,d,LOG;
vector<int> depth;
vector<vector<int> > par_table;
vector<quiz> qz;
vector<vector<int> > qz_uv;
vector<vector<int> > qz_par;
vector<edge> e;
vector<vector<int> > g;
vector<ll> color_dist;
vector<ll> color_num;
ll total_dist;
ll total_num;

int dfs_lca(int ide) {
  int from = e[ide].from;
  int idx = e[ide].to;

  par_table[idx][0] = from;

  //cout << "dfc_lca : idx = " << idx << endl;
  
  rep(i,g[idx].size()) {
    int child = e[g[idx][i]].to;
    if(child==from) continue;
    depth[child] = depth[idx]+1;
    dfs_lca(g[idx][i]);
  }
  
  return 0;
}

int make_table() {
  rep(i,LOG) {
    if(i==0) continue;
    rep(j,n) {
      par_table[j][i] = par_table[par_table[j][i-1]][i-1];
    }
  }

  return 0;
}

int lca(int u, int v) {
  if(depth[u]>depth[v]) {
    int tmp = u; u = v; v = tmp;
  }
  while(depth[u] < depth[v]) {
    int tmp = floor(log2(depth[v]-depth[u]));
    v = par_table[v][tmp];
    if(depth[u] > depth[v]) return -1;
  }

  if(u == v) return u;
  
  for(int i = LOG-1; i>=0; i--) {
    if(par_table[u][i] == par_table[v][i]) continue;
    u = par_table[u][i];
    v = par_table[v][i];
  }
  return par_table[u][0];;
}

int dfs(int ide) {
  int from = e[ide].from;
  int idx = e[ide].to;
  total_num++;
  total_dist += e[ide].dist;
  color_num[e[ide].color]++;
  color_dist[e[ide].color] += e[ide].dist;

  //cout << "dfs : idx = " << idx << ", total_num = " << total_num << endl;

  rep(i,qz_uv[idx].size()) {
    int idq = qz_uv[idx][i];
    ll cur_dist = total_dist - color_dist[qz[idq].x] + color_num[qz[idq].x]*qz[idq].y;
    qz[idq].ans += cur_dist;
  }

  rep(i,qz_par[idx].size()) {
    int idq = qz_par[idx][i];
    ll cur_dist = total_dist - color_dist[qz[idq].x] + color_num[qz[idq].x]*qz[idq].y;
    qz[idq].ans -= 2*cur_dist;
  }
  
  rep(i,g[idx].size()) {
    int child = e[g[idx][i]].to;
    if(child==from) continue;
    dfs(g[idx][i]);
  }

  total_num--;
  total_dist -= e[ide].dist;
  color_num[e[ide].color]--;
  color_dist[e[ide].color] -= e[ide].dist;
  return 0;
}


int main(int argc, char *argv[]) {
  int a,b,c,d;

#ifdef FILENAME
  ifstream file(FILENAME);
  cin.rdbuf(file.rdbuf());
#endif

  // input tree
  cin >> n >> q;
  g.resize(n);
  e.emplace_back(0,0,n,0);
  rep(i,n-1) {
    cin >> a >> b >> c >> d;
    a--;
    b--;
    c--;
    e.emplace_back(a,b,c,d); //cout << "e.size() = " << e.size() << endl;
    g[a].push_back(e.size()-1);
    e.emplace_back(b,a,c,d); //cout << "e.size() = " << e.size() << endl;
    g[b].push_back(e.size()-1);
  }

  /*
  //debug
  rep(i,n) {
    cout << i << ":" << endl;
    rep(j,g[i].size()) {
      int ide = g[i][j];
      cout << e[ide].from << " -> " << e[ide].to << endl;
    }
    cout << "\n";
  }
  */

  
  // preparetion for lca
  depth.resize(n);
  LOG = ceil(log2(n)); //cout << "main : LOG = " << LOG << endl;
  par_table.resize(n);
  rep(i,n) par_table[i].resize(LOG);
  dfs_lca(0); //cout << "dfs_lca done." << endl;
  make_table(); //cout << "make_table done." << endl;

 
  // input problems
  qz_uv.resize(n);
  qz_par.resize(n);
  qz.resize(q);
  rep(i,q) {
    int x,y,u,v;
    cin >> x >> y >> u >> v;
    int par_uv = lca(u-1,v-1);
    if(par_uv < 0) cout << "error\n";
    qz[i].init(x-1,y,u-1,v-1,par_uv);
    qz_uv[u-1].push_back(i);
    qz_uv[v-1].push_back(i);
    qz_par[par_uv].push_back(i);

    //debug
    //cout << "qz[" << i << "] : u = " << u << ", v = " << v << ", par = " << par_uv << endl;
  }
  

  
  // calculation
  depth.resize(n);
  depth[0] = 0;
  color_dist.resize(n+1,0);
  color_num.resize(n+1,0);
  total_dist = 0;
  total_num = 0;
  //cout << "start dfs\n";
  dfs(0);
  
  

  

  // out
  rep(i,qz.size()) {
    cout << qz[i].ans << endl;
  }
  
  
  return 0;
}


Measured memory_bytes: 38508