#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <cstdlib>
#include <fstream>
#include <climits>
#include <queue>
#include <map>
#include <set>

using namespace std;

struct Edge {
    int to, color, cost;

    Edge(int to, int color, int cost) : to(to), color(color), cost(cost) {}
};

struct Query {
    int color, cost, u, v, lca;

    Query(int color, int cost, int u, int v) : color(color), cost(cost), u(u), v(v) {}
};

vector<vector<Edge> > graph;
vector<int> total_cost;
vector<int> depth;
vector<int> parent;
vector<vector<int> > dp;
vector<Query> queries;
vector<set<int> > needed_colors;
map<int, pair<int, int> > freq;
vector<map<int, pair<int, int> > > node_freq;

void addEdge(int from, int to, int color, int cost) {
    graph[from].push_back(Edge(to, color, cost));
    graph[to].push_back(Edge(from, color, cost));
}

void DFS(int node, int current_parent, int current_cost, int current_depth) {
    parent[node] = current_parent;
    total_cost[node] = current_cost;
    depth[node] = current_depth;

    for (Edge &edge : graph[node]) {
        if (edge.to != current_parent) {
            DFS(edge.to, node, current_cost + edge.cost, current_depth + 1);
        }
    }
}

void buildLCA() {
    DFS(0, -1, 0, 0);
    dp.resize(graph.size(), vector<int>(20, -1));
    for (int i = 0; i < graph.size(); ++i)
        dp[i][0] = parent[i];
    for (int j = 1; j < 20; ++j) {
        for (int i = 0; i < graph.size(); ++i)
            if (dp[i][j - 1] != -1)
                dp[i][j] = dp[dp[i][j - 1]][j - 1];
    }
}

int getLCA(int u, int v) {
    if (depth[v] < depth[u])
        swap(u, v);
    int log = 0;
    while ((1 << log) <= depth[v])
        ++log;
    --log;
    for (int i = log; i >= 0; --i) {
        if (depth[v] - (1 << i) >= depth[u])
            v = dp[v][i];
    }
    if (u == v)
        return u;
    for (int i = log; i >= 0; --i) {
        if (dp[u][i] != dp[v][i]) {
            u = dp[u][i];
            v = dp[v][i];
        }
    }
    return dp[u][0];
}


void addNewQuery(int color, int cost, int u, int v) {
    queries.emplace_back(color, cost, u, v);
}

void addColor(int color, int cost) {
    auto it = freq.find(color);
    if (it == freq.end())
        freq[color] = make_pair(1, cost);
    else {
        freq[color] = make_pair(it->second.first + 1, it->second.second + cost);
    }
}

void removeColor(int color, int cost) {
    auto it = freq.find(color);
    if (it->second.first == 1)
        freq.erase(it);
    else
        freq[color] = make_pair(it->second.first - 1, it->second.second - cost);
}

void DFS(int node, int par) {
    for (int color : needed_colors[node]) {
        node_freq[node][color] = freq[color];
    }
    for (Edge &edge : graph[node]) {
        if (edge.to != par) {
            addColor(edge.color, edge.cost);
            DFS(edge.to, node);
            removeColor(edge.color, edge.cost);
        }
    }
}

int getColorCount(int node, int color) {
    return node_freq[node][color].first;
}

int countColorInPath(const Query &query) {
    return getColorCount(query.u, query.color) + getColorCount(query.v, query.color) -
           2 * getColorCount(query.lca, query.color);
}

int getColorCost(int node, int color) {
    return node_freq[node][color].second;
}

int calculateColorCostInPath(const Query &query) {
    return getColorCost(query.u, query.color) + getColorCost(query.v, query.color) -
           2 * getColorCost(query.lca, query.color);
}

int calculatePathCost(const Query &query) {
    return total_cost[query.u] + total_cost[query.v] - 2 * total_cost[query.lca];
}

int main(int argc, char **argv) {
    int n, q;
    scanf("%d%d", &n, &q);
    graph.resize(n);
    for (int i = 1; i < n; ++i) {
        int from, to, color, cost;
        scanf("%d%d%d%d", &from, &to, &color, &cost);
        --from, --to;
        addEdge(from, to, color, cost);
    }
    for (int i = 0; i < q; ++i) {
        int color, cost, u, v;
        scanf("%d%d%d%d", &color, &cost, &u, &v);
        --u, --v;
        addNewQuery(color, cost, u, v);
    }
    total_cost.resize(n);
    depth.resize(n);
    parent.resize(n);
    buildLCA();
    needed_colors.resize(n);
    for (Query &query : queries) {
        query.lca = getLCA(query.u, query.v);
        needed_colors[query.u].insert(query.color);
        needed_colors[query.v].insert(query.color);
        needed_colors[query.lca].insert(query.color);
    }
    needed_colors.resize(n);
    node_freq.resize(n);
    DFS(0, -1);
    for (Query &query : queries) {
        int color_count = countColorInPath(query);
        int color_cost = calculateColorCostInPath(query);
        int path_cost = calculatePathCost(query);
        int new_cost = path_cost - color_cost + color_count * query.cost;
        printf("%d\n", new_cost);
    }
    return 0;
}


Measured memory_bytes: 63280