using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Numerics;
using System.Threading.Tasks;
using static System.Console;
using static System.Math;
using static Func;
using static FuncT;
class Z { static void Main() => new K(); }
class K
{
	int F => int.Parse(Str);
	long FL => long.Parse(Str);
	int[] G => Strs.Select(int.Parse).ToArray();
	uint[] GU => Strs.Select(uint.Parse).ToArray();
	decimal[] GD => Strs.Select(decimal.Parse).ToArray();
	long[] GL => Strs.Select(long.Parse).ToArray();
	string Str => ReadLine();
	string[] Strs => Str.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
	static ulong One(int k) => 1ul << k;
	static ulong All(int k) => One(k) - 1;
	static bool Has(ulong s, int k) => (s & One(k)) != 0;
	const int MOD = 1000000007;
	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) + 5);
		dbl = new int[log, N];
		info[0] = FuncT.ConstructTree(MakeArray(2 * (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);
	public override string ToString() => $"Info(col={Color},cnt={Count},d={Distance})";
}
struct Pair
{
	public readonly int P, U;
	public Pair(int p, int u) { P = p; U = u; }
	public override string ToString() => $"Pair(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; }
	public override string ToString() => $"Edge(t={To},c={Color},l={Length})";
}
static class Func
{
	public static T[] ConstantArray<T>(int n, T val) { var a = new T[n]; for (var i = 0; i < n; i++) a[i] = val; return a; }
	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;
	public readonly int H, C;
	// l < v < r and |l.h - l.r| <= 2
	public Tree(Tree l, Info v, Tree r)
	{
		C = 1 + l.Count() + r.Count();
		var lh = l.Height();
		var rh = r.Height();
		if (lh > rh + 1)
		{
			if (l.L.Height() >= l.R.Height())
			{
				V = l.V;
				L = l.L;
				R = new Tree(l.R, v, r);
			}
			else
			{
				V = l.R.V;
				L = new Tree(l.L, l.V, l.R.L);
				R = new Tree(l.R.R, v, r);
			}
		}
		else if (rh > lh + 1)
		{
			if (r.R.Height() >= r.L.Height())
			{
				V = r.V;
				L = new Tree(l, v, r.L);
				R = r.R;
			}
			else
			{
				V = r.L.V;
				L = new Tree(l, v, r.L.L);
				R = new Tree(r.L.R, r.V, r.R);
			}
		}
		else
		{
			L = l;
			R = r;
			V = v;
		}
		H = 1 + Math.Max(L.Height(), R.Height());
	}
}
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 Join(list.ConstructTree(l, n), list[n], list.ConstructTree(n + 1, r));
	}
	public static int Count(this Tree t) => t?.C ?? 0;
	public static int Height(this Tree t) => t?.H ?? 0;
	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));
		}
	}
	// t1 < x < t2
	public static Tree Join(Tree t1, Info x, Tree t2)
	{
		var h1 = t1.Height();
		var h2 = t2.Height();
		if (Math.Abs(h1 - h2) <= 1) return new Tree(t1, x, t2);
		return h1 > h2 ? new Tree(t1.L, t1.V, Join(t1.R, x, t2)) : new Tree(Join(t1, x, t2.L), t2.V, t2.R);
	}
}


Measured memory_bytes: 151424