using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Console;
using static System.Math;
using static Func;
class Z { static void Main() => new K(); }
class K
{
	int[] G => ReadLine().Split().Select(int.Parse).ToArray();
	static bool Has(ulong s, int k) => (s & (1ul << k)) != 0;
	public K()
	{
		SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
		Solve();
		Out.Flush();
	}
	int N, log;
	int[] depth, depth2;
	int[,] dbl;
	List<Edge>[] g;
	Tree[] info;
	void Solve()
	{
		var I = G;
		N = I[0];
		var Q = I[1];
		g = MakeArray(N, _ => new List<Edge>());
		for (var i = 0; i < N - 1; i++)
		{
			I = G;
			g[I[0] - 1].Add(new Edge(I[1] - 1, I[2] - 1, I[3]));
			g[I[1] - 1].Add(new Edge(I[0] - 1, I[2] - 1, I[3]));
		}
		var s = new Stack<Pair>();
		s.Push(new Pair(-1, 0));
		info = MakeArray(N, _ => (Tree)null);
		depth = new int[N];
		depth2 = new int[N];
		log = (int)Ceiling(Log(N, 2) + 1);
		dbl = new int[log, N];
		info[0] = FuncT.ConstructTree(MakeArray(N - 1, c => new Info(c, 0, 0)).ToList());
		while (s.Count > 0)
		{
			var p = s.Pop();
			dbl[0, p.U] = p.P;
			foreach (var e in g[p.U])
				if (e.To != p.P) s.Push(new Pair(p.U, e.To));
				else if (p.P >= 0)
				{
					info[p.U] = info[p.P].Add(e);
					depth[p.U] = depth[p.P] + e.Length;
					depth2[p.U] = depth2[p.P] + 1;
				}
		}
		for (var l = 1; l < log; l++)
			for (var i = 0; i < N; i++)
				dbl[l, i] = dbl[l - 1, i] < 0 ? -1 : dbl[l - 1, dbl[l - 1, i]];
		for (var i = 0; i < Q; i++)
		{
			I = G;
			int c = I[0] - 1, d = I[1], u = I[2] - 1, v = I[3] - 1;
			WriteLine(Calc(c, d, u, v));
		}
	}
	int Calc(int c, int d, int u, int v)
	{
		var p = LCA(u, v);
		if (p < 0) return -1;
		var iu = info[u].Find(c).V;
		var iv = info[v].Find(c).V;
		var ip = info[p].Find(c).V;
		var cnt = iu.Count + iv.Count - 2 * ip.Count;
		var len = iu.Distance + iv.Distance - 2 * ip.Distance;
		return depth[u] + depth[v] - 2 * depth[p] - len + cnt * d;
	}
	int LCA(int u, int v)
	{
		if (depth2[u] > depth2[v]) return LCA(v, u);
		for (var l = 0; l < log; l++)
			if (Has((ulong)(depth2[v] - depth2[u]), l)) v = dbl[l, v];
		if (u == v) return u;
		for (var l = log - 1; l >= 0; l--)
			if (dbl[l, u] != dbl[l, v])
			{
				u = dbl[l, u];
				v = dbl[l, v];
			}
		return dbl[0, u];
	}
}
struct Info : IComparable<Info>
{
	public readonly int Distance, Count, Color;
	public Info(int col, int cnt, int d) { Distance = d; Count = cnt; Color = col; }

	public int CompareTo(Info other) => Color.CompareTo(other.Color);
	public static Info operator +(Info i, Edge e) => new Info(i.Color, i.Count + 1, i.Distance + e.Length);
}
struct Pair
{
	public readonly int P, U;
	public Pair(int p, int u) { P = p; U = u; }
}
struct Edge
{
	public readonly int To, Color, Length;
	public Edge(int t, int c, int l) { To = t; Color = c; Length = l; }
}
static class Func
{
	public static T[] MakeArray<T>(int n, Func<int, T> f) { var a = new T[n]; for (var i = 0; i < n; i++) a[i] = f(i); return a; }
}
class Tree
{
	public readonly Tree L, R;
	public readonly Info V;
	// l < v < r and |l.h - l.r| <= 2
	public Tree(Tree l, Info v, Tree r)
	{
		L = l;
		R = r;
		V = v;
	}
}
static class FuncT
{
	public static Tree ConstructTree(this IList<Info> list) => list.ConstructTree(0, list.Count);
	static Tree ConstructTree(this IList<Info> list, int l, int r)
	{
		if (l >= r) return null;
		var n = (l + r) / 2;
		return new Tree(list.ConstructTree(l, n), list[n], list.ConstructTree(n + 1, r));
	}
	public static Tree Find(this Tree t, int c)
	{
		if (t == null) return null;
		switch (t.V.Color.CompareTo(c))
		{
			case 1:
				return t.L.Find(c);
			case -1:
				return t.R.Find(c);
			default:
				return t;
		}
	}
	public static Tree Add(this Tree t, Edge e)
	{
		switch (t.V.Color.CompareTo(e.Color))
		{
			case 1:
				return new Tree(t.L.Add(e), t.V, t.R);
			case 0:
				return new Tree(t.L, t.V + e, t.R);
			default:
				return new Tree(t.L, t.V, t.R.Add(e));
		}
	}
}


Measured memory_bytes: 122888