#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <climits>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <map>
#include <tuple>
#include <iostream>
#include <deque>
#include <array>
#include <set>
#include <functional>
#include <memory>
#include <stack>



struct Path {
	int to, edge_id;
};
struct Edge {
	int a, b, color, length;
};
int upper_bound(const std::vector<int> &vec, const int value) {
	int left = 0; int right = vec.size();
	while (left < right) {
		auto mid = (left + right) / 2;
		if (vec[mid] <= value) {
			left = mid + 1;
		}
		else {
			right = mid;
		}
	}
	return right;
}

class Doubling {
	std::vector<std::vector<int>> prev;
	std::vector<int> depths;
	int up_to(const int a, const int depth) const {
		if (depths[a] == depth) return a;
		if (depths[a] < depth) throw "fail";
		int left = 0; int right = prev[a].size();
		while (left < right) {
			auto mid = (left + right) / 2;
			if (depths[prev[a][mid]] >= depth) {
				left = mid + 1;
			}
			else {
				right = mid;
			}
		}
		return up_to(prev[a][right - 1], depth);
	}
public:
	Doubling(const std::vector<std::vector<Path>>& nodes) : prev(nodes.size()), depths(nodes.size(), 0) {
		std::stack<int> stack; stack.push(0);
		while (!stack.empty()) {
			auto current = stack.top(); stack.pop();
			for (const auto next : nodes[current]) {
				if (next.to != 0 && prev[next.to].empty()) {
					depths[next.to] = depths[current] + 1;
					prev[next.to].push_back(current);
					stack.push(next.to);
					while (prev[next.to].size() <= prev[prev[next.to].back()].size()) {
						prev[next.to].push_back(prev[prev[next.to].back()][prev[next.to].size() - 1]);
					}
				}
			}
		}
	}
	int mlca(int a, int b) const {
		if (depths[a] < depths[b]) b = up_to(b, depths[a]);
		else a = up_to(a, depths[b]);
		if (a == b) return a;
		int left = 0; int right = std::min(prev[a].size(), prev[b].size());
		while (left < right) {
			auto mid = (left + right) / 2;
			if (prev[a][mid] != prev[b][mid]) {
				left = mid + 1;
			}
			else {
				right = mid;
			}
		}
		if (right == 0) return prev[a][0];
		else return mlca(prev[a][right - 1], prev[b][right - 1]);
	}
};
int main() {
	int n, q; std::cin >> n >> q;
	std::vector<std::vector<Path>> nodes(n + 1);
	std::vector<Edge> edges(n);
	nodes[0].push_back(Path({ 1, 0 }));
	edges[0] = Edge{ 0, 1, 0, 0 };
	for (auto i = 1; i < edges.size(); ++i) {
		std::cin >> edges[i].a >> edges[i].b >> edges[i].color >> edges[i].length;
		nodes[edges[i].a].push_back(Path{ edges[i].b, i });
		nodes[edges[i].b].push_back(Path{ edges[i].a, i });
	}
	Doubling doubling(nodes);
	std::vector<int> position_in_euler(n + 1, -1);
	position_in_euler[0] = 0;
	std::vector<int> euler;
	std::vector<std::vector<int>> position_in_colored(n, std::vector<int>{0});
	std::vector<std::vector<int>> colored_length(n, std::vector<int>{0});
	std::vector<std::vector<int>> colored_count(n, std::vector<int>{0});
	std::stack<Path> stack;
	stack.push(nodes[0][0]);
	while (!stack.empty()) {
		auto top = stack.top();
		if (position_in_euler[top.to] == -1) {
			position_in_euler[top.to] = euler.size();
			position_in_colored[edges[top.edge_id].color].push_back(euler.size());
			euler.push_back(edges[top.edge_id].length);
			colored_length[edges[top.edge_id].color].push_back(edges[top.edge_id].length);
			colored_count[edges[top.edge_id].color].push_back(1);
			for (const auto &next : nodes[top.to]) {
				if (position_in_euler[next.to] == -1) {
					stack.push(next);
				}
			}
		}
		else {
			stack.pop();
			position_in_colored[edges[top.edge_id].color].push_back(euler.size());
			euler.push_back(-edges[top.edge_id].length);
			colored_length[edges[top.edge_id].color].push_back(-edges[top.edge_id].length);
			colored_count[edges[top.edge_id].color].push_back(-1);
		}
	}
	for (auto i = 1; i < euler.size(); ++i) euler[i] += euler[i - 1];
	for (auto& colored : colored_length) for (auto i = 1; i < colored.size(); ++i) colored[i] += colored[i - 1];
	for (auto& colored : colored_count) for (auto i = 1; i < colored.size(); ++i) colored[i] += colored[i - 1];
	for (auto i = 0; i < q; ++i) {
		int x, y, u, v; std::cin >> x >> y >> u >> v;
		auto mlca = doubling.mlca(u, v);
		auto to_u = euler[position_in_euler[u]];
		auto to_v = euler[position_in_euler[v]];
		auto to_mlca = euler[position_in_euler[mlca]];
		auto colored_u = upper_bound(position_in_colored[x], position_in_euler[u]) - 1;
		auto colored_v = upper_bound(position_in_colored[x], position_in_euler[v]) - 1;
		auto colored_mlca = upper_bound(position_in_colored[x], position_in_euler[mlca]) - 1;
		auto length_colored_u = colored_length[x][colored_u];
		auto length_colored_v = colored_length[x][colored_v];
		auto length_colored_mlca = colored_length[x][colored_mlca];
		auto count_colored_u = colored_count[x][colored_u];
		auto count_colored_v = colored_count[x][colored_v];
		auto count_colored_mlca = colored_count[x][colored_mlca];
		auto default_distance = to_u + to_v - to_mlca * 2;
		auto default_colored = length_colored_u + length_colored_v - length_colored_mlca * 2;
		auto count_colored = count_colored_u + count_colored_v - count_colored_mlca * 2;
		std::cout << default_distance - default_colored + y * count_colored << std::endl;

	}
}

Measured memory_bytes: 39508