#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define int long long
using namespace std;
const int N = 2e5 + 50, INF = 123456789123456789;
int n, m;
int h[N], ne[N * 2], e[N * 2], w[N * 2], idx;
int fa[N], son[N], dist[N], dep[N], sz[N];
int id[N], cnt, top[N], rk[N];
struct Line {
int k, b;
Line() {}
Line(int x, int y) {k = x, b = y;}
};
struct Tree {
Line seg;
int val, l, r;
}tr[N << 3];
inline int calc(Line l, int x) {
return l.k * x + l.b;
}
void add(int a, int b, int c) {
ne[idx] = h[a], e[idx] = b, w[idx] = c, h[a] = idx ++;
}
void dfs(int u, int fath) {
fa[u] = fath, dep[u] = dep[fath] + 1, sz[u] = 1;
for(int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if(j == fath) continue;
dist[j] = dist[u] + w[i];
dfs(j, u);
sz[u] += sz[j];
if(sz[j] > sz[son[u]]) son[u] = j;
}
}
void dfs1(int u, int t) {
id[u] = ++ cnt, top[u] = t, rk[cnt] = u;
if(!son[u]) return ;
dfs1(son[u], t);
for(int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if(j == fa[u] || j == son[u]) continue;
dfs1(j, j);
}
}
inline int LCA(int u, int v) {
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
void pushup(int u) {
tr[u].val = min(tr[u].val, min(calc(tr[u].seg, dist[rk[tr[u].l]]), calc(tr[u].seg, dist[rk[tr[u].r]])));
tr[u].val = min(tr[u].val, min(tr[tr[u].l].val, tr[tr[u].r].val));
}
void build(int u, int l, int r) {
tr[u].seg.k = 0, tr[u].seg.b = INF;
tr[u].val = INF, tr[u].l = l, tr[u].r = r;
if(l == r) return ;
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}
void modify(int u, int s, int t, Line l) {
if(t < tr[u].l || s > tr[u].r) return ;
if(s <= tr[u].l && tr[u].r <= t) {
int mid = tr[u].l + tr[u].r >> 1;
if(calc(l, dist[rk[mid]]) < calc(tr[u].seg, dist[rk[mid]])) swap(tr[u].seg, l);
if(calc(l, dist[rk[tr[u].l]] < calc(tr[u].seg, dist[rk[tr[u].l]]))) modify(u << 1, s, t, l);
if(calc(l, dist[rk[tr[u].r]] < calc(tr[u].seg, dist[rk[tr[u].r]]))) modify(u << 1 | 1, s, t, l);
return pushup(u), void();
}
modify(u << 1, s, t, l), modify(u << 1 | 1, s, t, l);
pushup(u);
}
int query(int u, int s, int t) {
if(s <= tr[u].l && tr[u].r <= t) return tr[u].val;
int mid = tr[u].l + tr[u].r >> 1;
int ans = min(calc(tr[u].seg, dist[rk[max(tr[u].l, s)]]), calc(tr[u].seg, dist[rk[min(tr[u].r, t)]]));
if(s <= mid) ans = min(ans, query(u << 1, s, t));
if(mid < t) ans = min(ans, query(u << 1 | 1, s, t));
return ans;
}
int modifytree(int u, int v, Line l) {
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
modify(1, id[top[u]], id[u], l);
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
modify(1, id[v], id[u], l);
}
int querytree(int u, int v) {
int ans = INF;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ans = min(ans, query(1, id[top[u]], id[u]));
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
ans = min(ans, query(1, id[v], id[u]));
return ans;
}
signed main() {
memset(h, -1, sizeof h);
cin >> n >> m;
build(1, 1, n);
for(int i = 1; i < n; ++ i) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
dfs(1, 0), dfs1(1, 1);
while(m -- ) {
int op;
cin >> op;
if(op == 1) {
int s, t, a, b;
cin >> s >> t >> a >> b;
int lca = LCA(s, t);
modifytree(s, lca, Line (-a, a * dist[s] + b));
modifytree(lca, t, Line (a, a * dist[s] - 2 * a * dist[lca] + b));
}
else {
int s, t;
cin >> s >> t;
cout << querytree(s, t) << endl;
}
}
return 0;
}