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++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

/*input
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
*/
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<long long, null_type, less<long long>, rb_tree_tag, tree_order_statistics_node_update> indexed_set;
#pragma GCC optimize("unroll-loops,no-stack-protector")
//order_of_key #of elements less than x
// find_by_order kth element
typedef long long int ll;
#define ld long double
#define pii pair<int,int>
#define f first
#define s second
#define pb push_back
#define REP(i,n) for(ll i=0;i<n;i++)
#define sz(_a) (ll)(_a.size())
#define FILL(n) memset(n,0,sizeof(n))
#define ALL(_a) _a.begin(),_a.end()
const ll maxn=100005;
const ll maxlg=__lg(maxn)+2;
const ll INF64=8000000000000000000LL;
const int INF=0x3f3f3f3f;
const ll MOD=ll(1e9+7);
const ld PI=acos(-1);
const ld eps=1e-9;
ll mypow(ll a,ll b){
    ll res=1LL;
    while(b){
        if(b&1) res=res*a%MOD;
        a=a*a%MOD;
        b>>=1;
    }
    return res;
}
vector<pair<int,pii>> v[maxn];
bool vis[maxn];
int level[maxn];
int lcat[maxn][maxlg];
int par[maxn];
bool special[maxn];
int dist[maxn];
bool done[maxn];
map<int,pii> ans[maxn];
map<pii,pii> edge;
void dfs(int u){
    vis[u]=true;
    for(auto z:v[u]){
        int x=z.f;
        if(!vis[x]){
            level[x]=level[u]+1;
            par[x]=u;
            dist[x]=dist[u]+z.s.s;
            dfs(x);
        }
    }
}
map<int,pair<int,int>> mp;

void dfs2(int u){
    if(special[u]){
        ans[u]=mp;
    }
    vis[u]=true;
    for(auto z:v[u]){
        int x=z.f;
        if(!vis[x]){
            int d=z.s.s,c=z.s.f;
            if(mp.count(c)==0) mp.insert({c,{0,0}});
            mp[c].f++;
            mp[c].s+=d;
            dfs2(x);
            mp[c].f--;
            mp[c].s-=d;
            if(mp[c].f==0) mp.erase(c);
        }
    }
}
void prep(int n){
    REP(i,n){
        lcat[i][0]=par[i];
    }
    for(int j=1;j<maxlg;j++){
        REP(i,n){
            if(lcat[i][j-1]==-1) lcat[i][j]=-1;
            else lcat[i][j]=lcat[lcat[i][j-1]][j-1];

      //      cout<<lcat[i][j]<<' '<<i<<' '<<j<<'\n';
        }
    }
}
int lca(int a,int b){
    if(level[a]<level[b]){
        swap(a,b);
    }
    for(int j=maxlg-1;j>=0;j--){
        if(level[a]-(1<<j)>=level[b]){
            a=lcat[a][j];
        }
    }
    if(a==b) return a;
    for(int j=maxlg-1;j>=0;j--){
        if(lcat[a][j]!=-1 and lcat[b][j]!=-1 and lcat[a][j]!=lcat[b][j]){
            a=lcat[a][j];
            b=lcat[b][j];
        }
    }
    return lcat[a][0];
}
pii getdata(int u,int color){
    if(special[u]){
        if(ans[u][color].f==0) return {0,0};
        else return ans[u][color];
    }
    pii prev=getdata(par[u],color);
    if(edge[{u,par[u]}].f==color){
        prev.f++;
        prev.s+=edge[{u,par[u]}].s;
    }
    return prev;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
    FILL(vis);
    int n,q;
    cin>>n>>q;
    REP(i,n) par[i]=-1;
    memset(lcat,-1,sizeof(lcat));
    REP(i,n-1){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        --a;
        --b;
        v[a].pb({b,{c,d}});
        v[b].pb({a,{c,d}});
        edge[{a,b}]={c,d};
        edge[{b,a}]={c,d};
    }
    dist[0]=0;
    level[0]=0;
    dfs(0);
    prep(n);
    REP(i,n){
        special[i]=false;
        done[i]=false;
    }
    special[0]=true;
    done[0]=true;
    priority_queue<pii> pq;
    REP(i,n) pq.push({level[i],i});
    while(!pq.empty()){
        int a=pq.top().s;
        pq.pop();
        if(done[a]) continue;
        REP(i,350){
            a=par[a];
            if(special[a]) goto done2;
            done[a]=true;
        }
        special[a]=true;
        done2:;
    }
    dfs2(0);
    REP(i,q){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        --c;
        --d;
        int z=lca(c,d);
        pii a1=getdata(c,a),a2=getdata(d,a),a3=getdata(z,a);
 //       cout<<a1.f<<' '<<a2.f<<' '<<a3.f<<'\n';
        cout<<dist[c]+dist[d]-2*dist[z]+(a1.f*b-a1.s+a2.f*b-a2.s+2*(a3.f*b-a3.s))<<'\n';
    }
}