using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.IO;
using System.Text;
using System.Diagnostics;

using static util;
using P = pair<int, int>;

using Binary = System.Func<System.Linq.Expressions.ParameterExpression,
                           System.Linq.Expressions.ParameterExpression,
                           System.Linq.Expressions.BinaryExpression>;
using Unary = System.Func<System.Linq.Expressions.ParameterExpression,
                          System.Linq.Expressions.UnaryExpression>;

class Program {
    static StreamWriter sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
    static Scan sc = new Scan();
    const int M = 1000000007;
    const int M2 = 998244353;
    const long LM = 1L << 60;
    const double eps = 1e-11;
    static void Main(string[] args)
    {
        int n, q;
        sc.Multi(out n, out q);
        edge = new List<pair<int, P>>[n];
        var edge2 = new List<pair<long, int>>[n];
        needcol = new Dictionary<int, P>[n];
        var cols = new P[n];
        for (int i = 0; i < n; i++)
        {
            edge[i] =  new List<pair<int, P>>();
            edge2[i] =  new List<pair<long, int>>();
            needcol[i] = new Dictionary<int, P>();
            cols[i] = new P(0, 0);
        }
        for (int i = 0; i < n - 1; i++)
        {
            int u, v, c, d;
            sc.Multi(out u, out v, out c, out d);
            --u;
            --v;
            --c;
            edge[u].Add(new pair<int, P>(v, new P(c, d)));
            edge[v].Add(new pair<int, P>(u, new P(c, d)));
            edge2[u].Add(new pair<long, int>(d, v));
            edge2[v].Add(new pair<long, int>(d, u));
        }
        var lca = new LCATree(n, edge2);
        var que = new int[q][];
        for (int i = 0; i < q; i++)
        {
            que[i] = sc.IntArr;
            --que[i][0];
            --que[i][2];
            --que[i][3];
            int p = lca.getLCA(que[i][2], que[i][3]);
            if (!needcol[que[i][2]].ContainsKey(que[i][0]))
                needcol[que[i][2]].Add(que[i][0], new P(0, 0));
            if (!needcol[que[i][3]].ContainsKey(que[i][0]))
                needcol[que[i][3]].Add(que[i][0], new P(0, 0));
            if (!needcol[p].ContainsKey(que[i][0]))
                needcol[p].Add(que[i][0], new P(0, 0));
        }
        dfs(0, -1, cols);
        foreach (var item in que)
        {
            long d = lca.dist(item[2], item[3]);
            int p = lca.getLCA(item[2], item[3]);
            int cnt = needcol[item[2]][item[0]].v1 + needcol[item[3]][item[0]].v1 - needcol[p][item[0]].v1 * 2;
            int len = needcol[item[2]][item[0]].v2 + needcol[item[3]][item[0]].v2 - needcol[p][item[0]].v2 * 2;
            Prt(d - len + cnt * item[1]);
        }
        sw.Flush();
    }
    static List<pair<int, P>>[] edge;
    static Dictionary<int, P>[] needcol;
    static void dfs(int p, int par, P[] cols) {
        var dic = new Dictionary<int, P>();
        foreach (var item in needcol[p])
        {
            dic.Add(item.Key, new P(cols[item.Key].v1, cols[item.Key].v2));
        }
        needcol[p] = dic;
        foreach (var item in edge[p])
        {
            if (item.v1 == par) continue;
            ++cols[item.v2.v1].v1;
            cols[item.v2.v1].v2 += item.v2.v2;
            dfs(item.v1, p, cols);
            --cols[item.v2.v1].v1;
            cols[item.v2.v1].v2 -= item.v2.v2;
        }
    }

    static void DBG(string a) => Console.WriteLine(a);
    static void DBG<T>(IEnumerable<T> a) => DBG(string.Join(" ", a));
    static void DBG(params object[] a) => DBG(string.Join(" ", a));
    static void Prt(string a) => sw.WriteLine(a);
    static void Prt<T>(IEnumerable<T> a) => Prt(string.Join(" ", a));
    static void Prt(params object[] a) => Prt(string.Join(" ", a));
}
class pair<T, U> : IComparable<pair<T, U>> {
    public T v1;
    public U v2;
    public pair() : this(default(T), default(U)) {}
    public pair(T v1, U v2) { this.v1 = v1; this.v2 = v2; }
    public int CompareTo(pair<T, U> a) {
        int c = Comparer<T>.Default.Compare(v1, a.v1);
        return c != 0 ? c : Comparer<U>.Default.Compare(v2, a.v2);
    }
    public override string ToString() => v1 + " " + v2;
    public void Deconstruct(out T a, out U b) { a = v1; b = v2; }
    public static bool operator>(pair<T, U> a, pair<T, U> b) => a.CompareTo(b) > 0;
    public static bool operator<(pair<T, U> a, pair<T, U> b) => a.CompareTo(b) < 0;
    public static bool operator>=(pair<T, U> a, pair<T, U> b) => a.CompareTo(b) >= 0;
    public static bool operator<=(pair<T, U> a, pair<T, U> b) => a.CompareTo(b) <= 0;
}
static class util {
    public static pair<T, U> make_pair<T, U>(T v1, U v2) => new pair<T, U>(v1, v2);
    public static T sq<T>(T a) => Operator<T>.Multiply(a, a);
    public static T Max<T>(params T[] a) => a.Max();
    public static T Min<T>(params T[] a) => a.Min();
    public static bool inside(int i, int j, int h, int w) => i >= 0 && i < h && j >= 0 && j < w;
    static readonly int[] dd = { 0, 1, 0, -1 };
    static readonly string dstring = "RDLU";
    public static P[] adjacents(this P p) => adjacents(p.v1, p.v2);
    public static P[] adjacents(this P p, int h, int w) => adjacents(p.v1, p.v2, h, w);
    public static pair<P, char>[] adjacents_with_str(int i, int j)
        => Enumerable.Range(0, dd.Length).Select(k => new pair<P, char>(new P(i + dd[k], j + dd[k ^ 1]), dstring[k])).ToArray();
    public static pair<P, char>[] adjacents_with_str(int i, int j, int h, int w)
        => Enumerable.Range(0, dd.Length).Select(k => new pair<P, char>(new P(i + dd[k], j + dd[k ^ 1]), dstring[k])).Where(p => inside(p.v1.v1, p.v1.v2, h, w)).ToArray();
    public static P[] adjacents(int i, int j)
        => Enumerable.Range(0, dd.Length).Select(k => new P(i + dd[k], j + dd[k ^ 1])).ToArray();
    public static P[] adjacents(int i, int j, int h, int w)
        => Enumerable.Range(0, dd.Length).Select(k => new P(i + dd[k], j + dd[k ^ 1])).Where(p => inside(p.v1, p.v2, h, w)).ToArray();
    public static void Assert(bool cond) { if (!cond) throw new Exception(); }
    public static Dictionary<T, int> compress<T>(this IEnumerable<T> a)
        => a.Distinct().OrderBy(v => v).Select((v, i) => new { v, i }).ToDictionary(p => p.v, p => p.i);
    public static Dictionary<T, int> compress<T>(params IEnumerable<T>[] a) => compress(a.Aggregate(Enumerable.Union));
    public static void swap<T>(ref T a, ref T b) where T : struct { var t = a; a = b; b = t; }
    public static void swap<T>(this IList<T> a, int i, int j) where T : struct { var t = a[i]; a[i] = a[j]; a[j] = t; }
    public static T[] copy<T>(this IList<T> a) {
        var ret = new T[a.Count];
        for (int i = 0; i < a.Count; i++) ret[i] = a[i];
        return ret;
    }
}
static class Operator<T> {
    static readonly ParameterExpression x = Expression.Parameter(typeof(T), "x");
    static readonly ParameterExpression y = Expression.Parameter(typeof(T), "y");
    public static readonly Func<T, T, T> Add = Lambda(Expression.Add);
    public static readonly Func<T, T, T> Subtract = Lambda(Expression.Subtract);
    public static readonly Func<T, T, T> Multiply = Lambda(Expression.Multiply);
    public static readonly Func<T, T, T> Divide = Lambda(Expression.Divide);
    public static readonly Func<T, T> Plus = Lambda(Expression.UnaryPlus);
    public static readonly Func<T, T> Negate = Lambda(Expression.Negate);
    public static Func<T, T, T> Lambda(Binary op) => Expression.Lambda<Func<T, T, T>>(op(x, y), x, y).Compile();
    public static Func<T, T> Lambda(Unary op) => Expression.Lambda<Func<T, T>>(op(x), x).Compile();
}

class Scan {
    StreamReader sr;
    public Scan() { sr = new StreamReader(Console.OpenStandardInput()); }
    public Scan(string path) { sr = new StreamReader(path); }
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public string Str => sr.ReadLine().Trim();
    public pair<T, U> Pair<T, U>() {
        T a; U b;
        Multi(out a, out b);
        return new pair<T, U>(a, b);
    }
    public P P => Pair<int, int>();
    public int[] IntArr => StrArr.Select(int.Parse).ToArray();
    public long[] LongArr => StrArr.Select(long.Parse).ToArray();
    public double[] DoubleArr => StrArr.Select(double.Parse).ToArray();
    public string[] StrArr => Str.Split(new[]{' '}, StringSplitOptions.RemoveEmptyEntries);
    bool eq<T, U>() => typeof(T).Equals(typeof(U));
    T ct<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
    T cv<T>(string s) => eq<T, int>()    ? ct<T, int>(int.Parse(s))
                       : eq<T, long>()   ? ct<T, long>(long.Parse(s))
                       : eq<T, double>() ? ct<T, double>(double.Parse(s))
                       : eq<T, char>()   ? ct<T, char>(s[0])
                                         : ct<T, string>(s);
    public void Multi<T>(out T a) => a = cv<T>(Str);
    public void Multi<T, U>(out T a, out U b)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); }
    public void Multi<T, U, V>(out T a, out U b, out V c)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); }
    public void Multi<T, U, V, W>(out T a, out U b, out V c, out W d)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); }
    public void Multi<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
    { var ar = StrArr; a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]); }
}

class LCATree
{
    int m;
    int[][] parent;
    long[][] dis;
    int[] dep;
    public LCATree(int n, List<pair<long, int>>[] g)
    {
        parent = new int[n][];
        dis = new long[n][];
        dep = new int[n];
        m = 1;
        while ((1 << m - 1) < n) ++m;
        for (int i = 0; i < n; i++) {
            parent[i] = new int[m];
            dis[i] = new long[m];
            dep[i] = n + 1;
            for (int j = 0; j < m; j++) {
                parent[i][j] = -1;
                dis[i][j] = 1L << 60;
            }
        }
        dep[0] = 0;
        var q = new Queue<int>();
        q.Enqueue(0);
        while (q.Count > 0) {
            var p = q.Dequeue();
            foreach (var item in g[p]) {
                if (dep[item.v2] > dep[p] + 1) {
                    dep[item.v2] = dep[p] + 1;
                    parent[item.v2][0] = p;
                    dis[item.v2][0] = item.v1;
                    q.Enqueue(item.v2);
                }
            }
        }
        for (int i = 1; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (dep[j] >= (1 << i)) {
                    parent[j][i] = parent[parent[j][i - 1]][i - 1];
                    dis[j][i] = Math.Min(dis[j][i], dis[parent[j][i - 1]][i - 1] + dis[j][i - 1]);
                }
            }
        }
    }
    int climb(int a, int c, out long d)
    {
        d = 0;
        for (int i = m - 1; i >= 0 ; i--) {
            if (((c >> i) & 1) == 1) {
                d += dis[a][i];
                a = parent[a][i];
            }
        }
        return a;
    }
    public int getLCA(int a, int b) {
        if (dep[a] < dep[b]) {
            long d;
            b = climb(b, dep[b] - dep[a], out d);
        }
        else if (dep[a] > dep[b]) {
            long d;
            a = climb(a, dep[a] - dep[b], out d);
        }
        int p = m - 1;
        while (a != b && p >= 0) {
            if (parent[a][p] != parent[b][p]) {
                a = parent[a][p];
                b = parent[b][p];
            }
            else --p;
        }
        if (a != b) {
            return parent[a][0];
        }
        return a;
    }
    public long dist(int a, int b)
    {
        long res = 0;
        if (dep[a] < dep[b]) {
            long d;
            b = climb(b, dep[b] - dep[a], out d);
            res += d;
        }
        else if (dep[a] > dep[b]) {
            long d;
            a = climb(a, dep[a] - dep[b], out d);
            res += d;
        }
        int p = m - 1;
        while (a != b && p >= 0) {
            if (parent[a][p] != parent[b][p]) {
                res += dis[a][p] + dis[b][p];
                a = parent[a][p];
                b = parent[b][p];
            }
            else --p;
        }
        if (a != b) {
            res += dis[a][0] + dis[b][0];
        }
        return res;
    }
}


Measured memory_bytes: 197352