#include <iostream>
#include <utility>
#include <vector>
#include <array>
#include <tuple>
#include <unordered_map>
#include <algorithm>
#include <boost/functional/hash.hpp>

struct edge{ int dest, color, length; };
std::vector<std::vector<edge>> t_arr;
std::vector<std::array<int, 20>> parent_arr;
std::vector<int> nstep_arr;
std::vector<std::tuple<int, int, int, int, int>> queue_arr;
std::unordered_map<int, std::vector<int>> key_nodes;
std::unordered_map<std::tuple<int, int>, std::tuple<int, int, int>, boost::hash<std::tuple<int, int>>> node_info;

void dfs_parent(int current, int parent, int nstep){
  parent_arr[current][0] = parent;
  nstep_arr[current] = nstep;
  for(int k = 0; k < 20; k++){
    if(parent_arr[current][k] == -1) break;
    parent_arr[current][k+1] = parent_arr[parent_arr[current][k]][k];
  }
  for(const auto& it: t_arr.at(current)){
    if(it.dest==parent) continue;
    dfs_parent(it.dest, current, nstep+1);
  }
}

auto lca(int node1, int node2){
  if(nstep_arr[node1] > nstep_arr[node2]) std::swap(node1, node2);
  int nstep_diff = nstep_arr[node2]-nstep_arr[node1];
  int k = 0;
  while(nstep_diff > 0){
    if(nstep_diff & 1) node2 = parent_arr[node2][k];
    k++;
    nstep_diff >>= 1;
  }
  while(node1 != node2){
    int k2 = 0;
    while(parent_arr[node1][k2] != parent_arr[node2][k2]) k2++;
    k2 = std::max(0, k2-1);
    node1 = parent_arr[node1][k2];
    node2 = parent_arr[node2][k2];
  }
  return node1;
}

void dfs_color(int current, int parent, int length, std::vector<int>& current_clength, std::vector<int>& current_cnum){
  if(key_nodes.count(current) > 0){
    for(const auto& color: key_nodes[current]){
      node_info.insert(std::make_pair(std::make_tuple(current, color), std::make_tuple(length, current_clength[color], current_cnum[color])));
    }
  }
  for(const auto& it: t_arr.at(current)){
    if(it.dest==parent) continue;
    current_cnum[it.color]++;
    current_clength[it.color] += it.length;
    dfs_color(it.dest, current, length+it.length, current_clength, current_cnum);
    current_cnum[it.color]--;
    current_clength[it.color] -= it.length;
  }
}

int main(){
  int N,Q;
  std::cin >> N >> Q;
  t_arr.resize(N);
  for(int i = 0; i < N-1; i++){
    int a,b,c,d;
    std::cin >> a >> b >> c >> d;
    a--; b--; c--;
    t_arr[a].push_back(edge({b,c,d}));
    t_arr[b].push_back(edge({a,c,d}));
  }

  int N_bit = 0, tmp = N;
  while(tmp > 0){ tmp >>= 1; N_bit++; }
  parent_arr.resize(N);
  for(int i = 0; i < N; i++){
    for(int j = 0; j < 20; j++){
      parent_arr[i][j] = -1;
    }
  }
  nstep_arr.resize(N);
  dfs_parent(0, -1, 0);

  for(int i = 0; i < Q; i++){
    int x,y,u,v;
    std::cin >> x >> y >> u >> v;
    x--; u--; v--;
    int lcauv = lca(u,v);
    queue_arr.push_back(std::make_tuple(x,y,u,v,lcauv));
    if(std::find(key_nodes[u].begin(), key_nodes[u].end(), x) == key_nodes[u].end()) key_nodes[u].push_back(x);
    if(std::find(key_nodes[v].begin(), key_nodes[v].end(), x) == key_nodes[v].end()) key_nodes[v].push_back(x);
    if(std::find(key_nodes[lcauv].begin(), key_nodes[lcauv].end(), x) == key_nodes[lcauv].end()) key_nodes[lcauv].push_back(x);
  }

  std::vector<int> clength(N), cnum(N);
  dfs_color(0, -1, 0, clength, cnum);

  for(const auto& it: queue_arr){
    int x = std::get<0>(it), y = std::get<1>(it);
    auto ui = node_info[std::make_tuple(std::get<2>(it), x)];
    auto vi = node_info[std::make_tuple(std::get<3>(it), x)];
    auto uvi = node_info[std::make_tuple(std::get<4>(it), x)];
    auto l_change = [&](decltype(ui) l){ return std::get<0>(l)-std::get<1>(l)+y*std::get<2>(l); };
    int length = l_change(ui)+l_change(vi)-2*l_change(uvi);
    std::cout << length << "\n";
  }

  return 0;
}



Measured memory_bytes: 43848