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

struct edge{ int dest, color, length; };
struct queue_struct{ int x,y,u,v,lcauv; };
std::vector<std::vector<edge>> t_arr;
std::vector<std::array<int, 20>> parent_arr;
std::vector<int> nstep_arr;
std::vector<queue_struct> queue_arr;
std::unordered_map<int, std::unordered_set<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;
  scanf("%d%d", &N, &Q);
  t_arr.resize(N);
  for(int i = 0; i < N-1; i++){
    int a,b,c,d;
		scanf("%d%d%d%d", &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}));
  }

  parent_arr.resize(N, {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} );
  nstep_arr.resize(N);
  dfs_parent(0, -1, 0);

  queue_arr.resize(Q);
  for(int i = 0; i < Q; i++){
    queue_struct& q = queue_arr[i];
    scanf("%d%d%d%d", &q.x, &q.y, &q.u, &q.v);
    q.x--;
    q.u--;
    q.v--;
    q.lcauv = lca(q.u,q.v);
    key_nodes[q.u].insert(q.x);
    key_nodes[q.v].insert(q.x);
    key_nodes[q.lcauv].insert(q.x);
  }

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

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

  return 0;
}



Measured memory_bytes: 54772