You are given a directed weighted graph with n nodes and 2n - 2 edges. The nodes are labeled from 1 to n, while the edges are labeled from 1 to 2n - 2. The graph's edges can be split into two parts.

  * The first n - 1 edges will form a rooted spanning tree, with node 1 as the root. All these edges will point away from the root. 
  * The last n - 1 edges will be from node i to node 1, for all 2 ≤ i ≤ n. 



You are given q queries. There are two types of queries

  * 1 i w: Change the weight of the i-th edge to w
  * 2 u v: Print the length of the shortest path between nodes u to v



Given these queries, print the shortest path lengths.

Input

The first line of input will contain two integers n, q (2 ≤ n, q ≤ 200 000), the number of nodes, and the number of queries, respectively.

The next 2n - 2 integers will contain 3 integers ai, bi, ci, denoting a directed edge from node ai to node bi with weight ci.

The first n - 1 of these lines will describe a rooted spanning tree pointing away from node 1, while the last n - 1 of these lines will have bi = 1.

More specifically, 

  * The edges (a1, b1), (a2, b2), ... (an - 1, bn - 1) will describe a rooted spanning tree pointing away from node 1. 
  * bj = 1 for n ≤ j ≤ 2n - 2. 
  * an, an + 1, ..., a2n - 2 will be distinct and between 2 and n. 



The next q lines will contain 3 integers, describing a query in the format described in the statement.

All edge weights will be between 1 and 106.

Output

For each type 2 query, print the length of the shortest path in its own line.

Example

Input

5 9
1 3 1
3 2 2
1 4 3
3 5 4
5 1 5
3 1 6
2 1 7
4 1 8
2 1 1
2 1 3
2 3 5
2 5 2
1 1 100
2 1 3
1 8 30
2 4 2
2 2 4


Output

0
1
4
8
100
132
10
#include <bits/stdc++.h>
using namespace std;
namespace IO {
char buf[1 << 23], *p1 = buf, *p2 = buf;
template <typename T>
inline void read(T& x) {
  x = 0;
  register char ch =
      (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2)
           ? EOF
           : *p1++);
  while (!(ch >= 48 && ch <= 57))
    ch =
        (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2)
             ? EOF
             : *p1++);
  while ((ch >= 48 && ch <= 57)) {
    x = (x << 1) + (x << 3) + (ch ^ 48);
    ch =
        (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2)
             ? EOF
             : *p1++);
  }
}
template <typename T, typename... Args>
inline void read(T& t, Args&... args) {
  read(t);
  read(args...);
}
}  // namespace IO
using namespace IO;
const long long N = 2e5 + 10, inf = 1e18;
struct SegTree {
  long long l[N << 2], r[N << 2];
  long long mn[N << 2], tag[N << 2];
  inline void push_up(long long i) { mn[i] = min(mn[i << 1], mn[i << 1 | 1]); }
  inline void push_down(long long i) {
    mn[i << 1] += tag[i];
    mn[i << 1 | 1] += tag[i];
    tag[i << 1] += tag[i];
    tag[i << 1 | 1] += tag[i];
    tag[i] = 0;
  }
  void build(long long i, long long x, long long y) {
    l[i] = x;
    r[i] = y;
    if (x == y) return;
    build(i << 1, x, (x + y) >> 1);
    build(i << 1 | 1, ((x + y) >> 1) + 1, y);
  }
  void update(long long i, long long x, long long y, long long k) {
    if (l[i] >= x && r[i] <= y) {
      mn[i] += k;
      tag[i] += k;
      return;
    }
    push_down(i);
    if (r[i << 1] >= x) update(i << 1, x, y, k);
    if (l[i << 1 | 1] <= y) update(i << 1 | 1, x, y, k);
    push_up(i);
  }
  long long query(long long i, long long x, long long y) {
    if (l[i] >= x && r[i] <= y) return mn[i];
    push_down(i);
    long long ans = inf;
    if (r[i << 1] >= x) ans = min(ans, query(i << 1, x, y));
    if (l[i << 1 | 1] <= y) ans = min(ans, query(i << 1 | 1, x, y));
    push_up(i);
    return ans;
  }
};
SegTree dis1, dis2;
long long n, m, cnt, u[N << 2], v[N << 2], c[N << 2], f[N], dfn[N], siz[N],
    dep[N];
vector<pair<long long, long long> > edge[N];
long long dfs(long long u, long long sum, long long depth) {
  cnt++;
  dep[u] = depth;
  dfn[u] = cnt;
  siz[u] = 1;
  dis1.update(1, dfn[u], dfn[u], sum);
  dis2.update(1, dfn[u], dfn[u], sum + f[u]);
  for (long long i = 0; i < edge[u].size(); i++)
    siz[u] += dfs(edge[u][i].first, sum + edge[u][i].second, dep[u] + 1);
  return siz[u];
}
int main() {
  read(n, m);
  dis1.build(1, 1, n);
  dis2.build(1, 1, n);
  for (long long i = 1; i <= n - 1; i++) {
    read(u[i], v[i], c[i]);
    edge[u[i]].push_back(make_pair(v[i], c[i]));
  }
  for (long long i = n; i <= 2 * n - 2; i++) {
    read(u[i], v[i], c[i]);
    f[u[i]] = c[i];
  }
  dfs(1ll, 0ll, 1ll);
  while (m--) {
    long long op, x, y;
    read(op, x, y);
    if (op == 1)
      if (x <= n - 1) {
        dis1.update(1ll, dfn[v[x]], dfn[v[x]] + siz[v[x]] - 1, y - c[x]);
        dis2.update(1ll, dfn[v[x]], dfn[v[x]] + siz[v[x]] - 1, y - c[x]);
        c[x] = y;
      } else {
        dis2.update(1ll, dfn[u[x]], dfn[u[x]], y - f[u[x]]);
        f[u[x]] = y;
      }
    else if (dfn[x] <= dfn[y] && dfn[x] + siz[x] - 1 >= dfn[y])
      printf("%lld\n",
             dis1.query(1ll, dfn[y], dfn[y]) - dis1.query(1ll, dfn[x], dfn[x]));
    else
      printf("%lld\n", dis2.query(1ll, dfn[x], dfn[x] + siz[x] - 1) -
                           dis1.query(1ll, dfn[x], dfn[x]) +
                           dis1.query(1ll, dfn[y], dfn[y]));
  }
  return 0;
}
