#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1e5 + 5;
const int INF = 1e15;
struct Seg {
int n;
vector<int> mn, dist, lz;
void init(int sz) {
n = sz;
mn.assign(4 * n + 5, INF);
dist.assign(4 * n + 5, 0);
lz.assign(4 * n + 5, 0);
}
void build(int id, int l, int r, vector<int>& a) {
if(l == r) { dist[id] = a[l]; return; }
int mid = (l + r) / 2;
build(id * 2, l, mid, a);
build(id * 2 + 1, mid + 1, r, a);
dist[id] = min(dist[id * 2], dist[id * 2 + 1]);
}
void down(int id) {
if(!lz[id]) return;
for(int i = 0; i < 2; i++) {
int c = id * 2 + i;
if(mn[c] < INF / 2) mn[c] += lz[id];
dist[c] += lz[id];
lz[c] += lz[id];
}
lz[id] = 0;
}
void up_range(int id, int l, int r, int u, int v, int val) {
if(l > v || r < u) return;
if(u <= l && r <= v) {
if(mn[id] < INF / 2) mn[id] += val;
dist[id] += val;
lz[id] += val;
return;
}
down(id);
int mid = (l + r) / 2;
up_range(id * 2, l, mid, u, v, val);
up_range(id * 2 + 1, mid + 1, r, u, v, val);
mn[id] = min(mn[id * 2], mn[id * 2 + 1]);
dist[id] = min(dist[id * 2], dist[id * 2 + 1]);
}
void up_point(int id, int l, int r, int p, int has) {
if(l == r) {
mn[id] = has ? dist[id] : INF;
return;
}
down(id);
int mid = (l + r) / 2;
if(p <= mid) up_point(id * 2, l, mid, p, has);
else up_point(id * 2 + 1, mid + 1, r, p, has);
mn[id] = min(mn[id * 2], mn[id * 2 + 1]);
}
int get_dist(int id, int l, int r, int p) {
if(l == r) return dist[id];
down(id);
int mid = (l + r) / 2;
if(p <= mid) return get_dist(id * 2, l, mid, p);
return get_dist(id * 2 + 1, mid + 1, r, p);
}
};
vector<array<int, 2>> g[maxn];
int sz[maxn], del[maxn], par[maxn], lvl[maxn];
int tin[20][maxn], tout[20][maxn], timer[maxn];
Seg st[maxn];
int get_sz(int u, int p) {
sz[u] = 1;
for(auto [v, w] : g[u]) {
if(v != p && !del[v]) sz[u] += get_sz(v, u);
}
return sz[u];
}
int centroid(int u, int p, int targ) {
for(auto [v, w] : g[u]) {
if(v != p && !del[v] && sz[v] > targ / 2) return centroid(v, u, targ);
}
return u;
}
void dfs_comp(int u, int p, int d, int l, int c, vector<int>& init_d) {
tin[l][u] = ++timer[c];
init_d.push_back(d);
for(auto [v, w] : g[u]) {
if(v != p && !del[v]) dfs_comp(v, u, d + w, l, c, init_d);
}
tout[l][u] = timer[c];
}
void decompose(int u, int p, int l) {
u = centroid(u, -1, get_sz(u, -1));
del[u] = 1;
par[u] = p;
lvl[u] = l;
vector<int> init_d;
init_d.push_back(0);
timer[u] = 0;
dfs_comp(u, -1, 0, l, u, init_d);
st[u].init(timer[u]);
st[u].build(1, 1, timer[u], init_d);
for(auto [v, w] : g[u]) {
if(!del[v]) decompose(v, u, l + 1);
}
}
signed main() {
ios_base::sync_with_stdio(0); cin.tie(0);
int n, q; cin >> n >> q;
map<pair<int, int>, int> ew;
for(int i = 1; i < n; i++) {
int u, v, w; cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
ew[{min(u, v), max(u, v)}] = w;
}
decompose(1, 0, 1);
vector<int> at(n + 1, 0);
while(q--) {
int type; cin >> type;
if(type == 1) {
int x; cin >> x;
int ans = INF, cur = x;
while(cur) {
int l = lvl[cur];
int d = st[cur].get_dist(1, 1, st[cur].n, tin[l][x]);
ans = min(ans, d + st[cur].mn[1]);
cur = par[cur];
}
cout << (ans >= INF / 2 ? -1 : ans) << "\n";
}
else if(type == 2) {
int x; cin >> x;
at[x] ^= 1;
int cur = x;
while(cur) {
int l = lvl[cur];
st[cur].up_point(1, 1, st[cur].n, tin[l][x], at[x]);
cur = par[cur];
}
}
else {
int u, v, w; cin >> u >> v >> w;
int delta = w - ew[{min(u, v), max(u, v)}];
ew[{min(u, v), max(u, v)}] = w;
vector<int> pu, pv;
int cu = u; while(cu) { pu.push_back(cu); cu = par[cu]; }
int cv = v; while(cv) { pv.push_back(cv); cv = par[cv]; }
int i = pu.size() - 1, j = pv.size() - 1;
while(i >= 0 && j >= 0 && pu[i] == pv[j]) {
int c = pu[i];
int l = lvl[c];
int child = (tin[l][u] > tin[l][v]) ? u : v;
st[c].up_range(1, 1, st[c].n, tin[l][child], tout[l][child], delta);
i--; j--;
}
}
}
return 0;
}