Problem:
Score : 600 points

Problem Statement

There is a tree with N vertices numbered 1 to N.
The i-th edge in this tree connects Vertex a_i and Vertex b_i, and the color and length of that edge are c_i and d_i, respectively.
Here the color of each edge is represented by an integer between 1 and N-1 (inclusive). The same integer corresponds to the same color, and different integers correspond to different colors.

Answer the following Q queries:

Query j (1 \leq j \leq Q): assuming that the length of every edge whose color is x_j is changed to y_j, find the distance between Vertex u_j and Vertex v_j. (The changes of the lengths of edges do not affect the subsequent queries.)

Constraints

2 \leq N \leq 10^5

1 \leq Q \leq 10^5

1 \leq a_i, b_i \leq N

1 \leq c_i \leq N-1

1 \leq d_i \leq 10^4

1 \leq x_j \leq N-1

1 \leq y_j \leq 10^4

1 \leq u_j < v_j \leq N

The given graph is a tree.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
a_1 b_1 c_1 d_1
:
a_{N-1} b_{N-1} c_{N-1} d_{N-1}
x_1 y_1 u_1 v_1
:
x_Q y_Q u_Q v_Q

Output

Print Q lines. The j-th line (1 \leq j \leq Q) should contain the answer to Query j.

Sample Input 1

5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4

Sample Output 1

130
200
60

The graph in this input is as follows:

Here the edges of Color 1 are shown as solid red lines, the edge of Color 2 is shown as a bold green line, and the edge of Color 4 is shown as a blue dashed line.

Query 1: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 4 is 100 + 30 = 130.

Query 2: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 5 is 100 + 100 = 200.

Query 3: Assuming that the length of every edge whose color is 3 is changed to 1000 (there is no such edge), the distance between Vertex 3 and Vertex 4 is 20 + 10 + 30 = 60. Note that the edges of Color 1 now have their original lengths.

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Linq;
using System.Collections.Generic;
using static System.Console;
using System.Text;
using System.IO;


namespace AtCoder_Beginner_Contest_132
{
    class Program
    {
        //解説動画参照(https://www.youtube.com/watch?v=8uowVvQ_-Mo)
        class lca
        {
            int n, root, l;
            List<int>[] to;         //tree
            List<long>[] co;        //ノードから出てる枝の長さ
            int[] dep;              //ルート-ノード間の枝の数(枝の長さ1としたときの距離)
            public long[] costs;    //ルート-ノード間の距離
            List<int>[] par;        //ノードの2^n個前のノード(1,2,4,･･･個前)
            public lca(int n)
            {
                this.n = n;
                to = new List<int>[n];
                co = new List<long>[n];
                for (var i = 0; i < n; ++i)
                {
                    to[i] = new List<int>();
                    co[i] = new List<long>();
                }
                dep = new int[n];
                costs = new long[n];
                this.l = 0;
                while ((1 << (int)l) < n) ++l;
                par = new List<int>[n + 1];
                for (var i = 0; i < n + 1; ++i)
                {
                    par[i] = new List<int>();
                    for (var j = 0; j < l; ++j)
                    { par[i].Add(n); }
                }
            }
            //頂点a,bを長さcの枝で接続
            public void addEdge(int a, int b, long c = 0)
            {
                to[a].Add(b); co[a].Add(c);
                to[b].Add(a); co[b].Add(c);
            }
            //深さ優先探索
            //dは枝の長さ1とした場合
            //cは距離
            //pはpre
            void dfs(int v, int d = 0, long c = 0, int p = -1)
            {
                if (p != -1) par[v][0] = p;
                dep[v] = d;
                costs[v] = c;
                for (var i = 0; i < to[v].Count; ++i)
                {
                    var u = to[v][i];
                    if (u == p) continue;
                    dfs(u, d + 1, c + co[v][i], v);
                }
            }
            //tree,距離1、距離2、
            public void init(int _root = 0)
            {
                root = _root;
                dfs(root);
                for (var i = 0; i < l - 1; ++i)
                {
                    for (var v = 0; v < n; ++v)
                    {
                        par[v][i + 1] = par[par[v][i]][i];
                    }
                }
            }
            //lca
            public int ope(int a, int b)
            {
                if (dep[a] > dep[b])//swap
                {
                    var t = a;
                    a = b;
                    b = a;
                }
                int gap = dep[b] - dep[a];
                for (var i = l - 1; 0 <= i; --i)//aと同じ距離になるまでbを前に
                {
                    int len = 1 << i;
                    if (gap >= len)
                    {
                        gap -= len;
                        b = par[b][i];
                    }
                }
                if (a == b) return a;
                for (var i = l - 1; 0 <= i; --i)//同じノードの直前まで
                {
                    var na = par[a][i];
                    var nb = par[b][i];
                    if (na != nb) { a = na; b = nb; }
                }
                return par[a][0];//同じノード
            }
            //a,b間の枝の数
            int length(int a, int b)
            {
                int c = ope(a, b);
                return dep[a] + dep[b] - dep[c] * 2;
            }
            //a,b間の距離
            public long dist(int a, int b)
            {
                int c = ope(a, b);
                return costs[a] + costs[b] - costs[c] * 2;
            }
        }
        class Edge
        {
            public int to, co, col;
            public Edge(int to, int co, int col)//接続先、長さ、色
            {
                this.to = to;
                this.co = co;
                this.col = col;
            }
        }
        class Query
        {
            public int col, qid, coeff, y;
            public Query(int col, int qid, int coeff, int y)//色、クエリ番号、係数、長さ
            {
                this.col = col;
                this.qid = qid;
                this.coeff = coeff;
                this.y = y;
            }
        }

        //解説
        static public long[] Sarray() { return ReadLine().Split().Select(long.Parse).ToArray(); }
        static public List<long> Slist() { return ReadLine().Split().Select(long.Parse).ToList(); }
        const long Mod = 1000000000 + 7;
        static void Main(string[] args)
        {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);

            var NQ = Sarray();
            var N = NQ[0];
            var Q = NQ[1];
            var g = new lca((int)N);
            var es = new List<Edge>[N];//tree(接続先、色、長さ)

            for (var i = 0; i < N; ++i)
            { es[i] = new List<Edge>(); }
            for (var i = 0; i < N - 1; ++i)
            {
                var abcd = Sarray();
                var a = (int)abcd[0] - 1;
                var b = (int)abcd[1] - 1;
                var c = (int)abcd[2];
                var d = (int)abcd[3];
                es[a].Add(new Edge(b, d, c));
                es[b].Add(new Edge(a, d, c));
                g.addEdge(a, b, d);
            }
            g.init();
            var ans = new long[Q];
            var qs = new List<Query>[N];
            for (var i = 0; i < N; ++i)
            { qs[i] = new List<Query>(); }
            for (var i = 0; i < Q; ++i)
            {
                var xyab = Sarray();
                var x = (int)xyab[0];
                var y = (int)xyab[1];
                var a = (int)xyab[2] - 1;
                var b = (int)xyab[3] - 1;
                var c = g.ope(a, b);
                ans[i] = g.costs[a] + g.costs[b] - g.costs[c] * 2;//クエリiに対する準備(長さ変更前の長さ)
                qs[a].Add(new Query(x, i, 1, y));
                qs[b].Add(new Query(x, i, 1, y));
                qs[c].Add(new Query(x, i, -2, y));
            }
            var sum = new long[N + 1];  //色ごとの枝の長さ
            var cnt = new int[N + 1];   //色ごとの枝の数
            Action<int, int> dfs2 = null;
            dfs2 = (v, p) =>
              {
                  foreach (var q in qs[v])//ノードvに対するクエリを処理
                  {
                      long x = -sum[q.col];
                      x += (long)q.y * cnt[q.col];  //対称色に対する長さ変更の処理
                      ans[q.qid] += x * q.coeff;    //ansに加える(lcaなら-2,ノードなら+1)
                  }
                  foreach (var e in es[v])
                  {
                      if (e.to == p) continue;
                      cnt[e.col]++; sum[e.col] += e.co;//ノードまでの色の枝
                      dfs2(e.to, v);
                      cnt[e.col]--; sum[e.col] -= e.co;//減らす
                  }
              };
            dfs2(0, -1);
            for (var i = 0; i < Q; ++i)
            { WriteLine($"{ans[i]}"); }
            Console.Out.Flush();
        }
    }
}