#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define REP(i,n) for(int i=0,_n=(int)(n);i<_n;++i)
#define ALL(v) (v).begin(),(v).end()
#define CLR(t,v) memset(t,(v),sizeof(t))
template<class T1,class T2>ostream& operator<<(ostream& os,const pair<T1,T2>&a){return os<<"("<<a.first<<","<<a.second<< ")";}
template<class T>void pv(T a,T b){for(T i=a;i!=b;++i)cout<<(*i)<<"\t";cout<<endl;}
template<class T>void chmin(T&a,const T&b){if(a>b)a=b;}
template<class T>void chmax(T&a,const T&b){if(a<b)a=b;}


int nextInt() { int x; scanf("%d", &x); return x;}
ll nextLong() { ll x; scanf("%lld", &x); return x;}

const int MAX_N = 100000 + 10;
const int SZ = MAX_N * 2 + 10;

struct E{
  int to;
  int color;
  int dist;
};
vector<E> g[MAX_N];

/**
* Sparse Table による RMQ の実装。
* 区間のmin
* 構築O(nlogn), クエリO(1)
* 更新ができない。
* SegmentTreeによる実装よりも定数倍がかなり高速。
*/
struct RMQStatic {
  int *a;
  int dp_min[20][SZ]; // [i][j] := answer index of start_pos == j, len == 2^i

  int log2(int b) {return 31 - __builtin_clz(b);}

  // O(NlogN)
  void build(int* a, int N) {
    this->a = a;
    int M = log2(N) + 1;
    REP(i, N) dp_min[0][i] = i;
    for (int i = 1, len = 1; i < M; i++, len <<= 1) {
      for (int j = 0; j + len < N; j++) {
        {
          int s = dp_min[i - 1][j];
          int t = dp_min[i - 1][j + len];
          dp_min[i][j] = a[s] <= a[t] ? s : t;
        }
      }
    }
  }

  // O(1)
  // [from..to]の間で最小の値の添字を返す。複数ある場合は一番最初のを返す
  int query(int from, int to) {
    int k = log2(to - from + 1);
    int s = dp_min[k][from];
    int t = dp_min[k][to - (1 << k) + 1];
    return a[s] <= a[t] ? s : t;
  }
};

int nod[SZ]; // dfsして i 番目に訪問した頂点の番号
int dep[SZ]; // dfsして i 番目に訪問した頂点の深さ
int dist[SZ]; // root からの距離
int apr[MAX_N]; // nod において頂点 v が始めに出現する添字

void dfs(int v, int prev, int d, int dis, int& sp) {
  if (apr[v] == -1)
    apr[v] = sp;
  nod[sp] = v;
  dep[sp] = d;
  dist[sp] = dis;
  sp++;
  for (auto e : g[v]) if (e.to != prev) {
    dfs(e.to, v, d + 1, dis + e.dist, sp);
    nod[sp] = v; dep[sp] = d; dist[sp] = dis; sp++;
  }
}

RMQStatic rmq;

struct Query {
  int x;
  int y;
  int u;
  int v;
};

vector<int> require[MAX_N]; // v -> colors
map<int,int> ps_num;
map<int,int> ps_sum;
map< pair<int,int>, int > ps_num_ans;
map< pair<int,int>, int > ps_sum_ans;
void dfs2(int u, int prev) {

  for (int color: require[u]) {
    ps_num_ans[ {u, color} ] = ps_num[color];
    ps_sum_ans[ {u, color} ] = ps_sum[color];
  }

  for (auto e : g[u]) if (e.to != prev) {
    ps_num[e.color]++;
    ps_sum[e.color] += e.dist;
    dfs2(e.to, u);
    ps_num[e.color]--;
    ps_sum[e.color] -= e.dist;
  }
}

int main2() {

  REP(i, MAX_N) g[i].clear();
  REP(i, MAX_N) require[i].clear();

  int N = nextInt();
  int Q = nextInt();

  REP(i, N-1) {
    int a = nextInt() - 1;
    int b = nextInt() - 1;
    int c = nextInt();
    int d = nextInt();
    g[a].push_back({b, c, d});
    g[b].push_back({a, c, d});
  }

  int sp = 0;
  CLR(apr, -1);
  dfs(0, -1, 0, 0, sp);
  rmq.build(dep, sp);

  vector<Query> query;
  REP(q, Q) {
    int x = nextInt();
    int y = nextInt();
    int u = nextInt() - 1;
    int v = nextInt() - 1;
    query.push_back((Query){x, y, u, v});
    int ui = min(apr[u], apr[v]);
    int vi = max(apr[u], apr[v]);
    int m = rmq.query(ui, vi);
    require[u].push_back(x);
    require[v].push_back(x);
    require[nod[m]].push_back(x);
  }

  ps_num.clear();
  ps_sum.clear();
  ps_num_ans.clear();
  ps_sum_ans.clear();
  dfs2(0, -1);

  REP(q, Q) {
    int x = query[q].x;
    int y = query[q].y;
    int u = query[q].u;
    int v = query[q].v;

    int ui = min(apr[u], apr[v]);
    int vi = max(apr[u], apr[v]);
    int m = rmq.query(ui, vi);

    int orgDist = dist[ui] + dist[vi] - 2 * dist[m];

    int num = ps_num_ans[{u, x}] + ps_num_ans[{v, x}] - 2 * ps_num_ans[{nod[m], x}];
    int sum = ps_sum_ans[{u, x}] + ps_sum_ans[{v, x}] - 2 * ps_sum_ans[{nod[m], x}];

    int ans = orgDist - sum + y * num;
    printf("%d\n", ans);
  }

  return 0;
}

int main() {

#ifdef LOCAL
  for (;!cin.eof();cin>>ws)
#endif
    main2();
  return 0;
}

Measured memory_bytes: 73008