#include <iostream> #include <algorithm> #include <vector> #include <cstdio> #include <cstring> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int maxn = 200020; const long long INF = 1e18; int n, m, total, edge_size; int fa[maxn], pos[maxn], son[maxn], depth[maxn], _size[maxn], _top[maxn], edge_id[maxn]; long long seg_tree[maxn<<2], edge_value[maxn]; struct Edge { int from, to; long long dist; }; vector<Edge> edges; vector<int> G[maxn]; void init() { total = edge_size = 0; memset(son, -1, sizeof(son)); for(int i=0; i<=n; i++) G[i].clear(); edges.clear(); } void AddEdge(int u, int v, long long w) { edges.push_back((Edge){u, v, w}); G[u].push_back(edge_size); edge_size++; } void DFS(int u, int pre, int deep) { fa[u] = pre; depth[u] = deep; _size[u] = 1; for(int i=0; i<G[u].size(); i++) { Edge e = edges[G[u][i]]; if(e.to == pre) continue; DFS(e.to, u, deep+1); _size[u] += _size[e.to]; if(son[u] == -1 || _size[e.to] > _size[son[u]]) { son[u] = e.to; } } } void BuildTree(int u, int TOP) { pos[u] = ++total; _top[u] = TOP; if(son[u] == -1) return ; BuildTree(son[u], TOP); for(int i=0; i<G[u].size(); i++) { int v = edges[G[u][i]].to; if(v != fa[u] && v != son[u]) { BuildTree(v, v); } } } long long Mul(long long a, long long b) { if(a == 0 || b == 0) return 0; if(INF / a < b) return 0; return a * b; } void PushUp(int rt) { seg_tree[rt] = Mul(seg_tree[rt<<1], seg_tree[rt<<1|1]); } void BuildSegTree(int l, int r, int rt) { seg_tree[rt] = 1; if(l == r) return ; int m = (l + r) >> 1; BuildSegTree(lson); BuildSegTree(rson); } void Update(int p, long long val, int l, int r, int rt) { if(l == r) { seg_tree[rt] = val; return ; } int m = (l + r) >> 1; if(p <= m) Update(p, val, lson); else Update(p, val, rson); PushUp(rt); } long long Query(int L, int R, int l, int r, int rt) { if(L <= l && R >= r) { return seg_tree[rt]; } int m = (l + r) >> 1; long long ret = 1; if(L <= m) ret = Mul(ret, Query(L, R, lson)); if(R > m) ret = Mul(ret, Query(L, R, rson)); return ret; } long long Calc(int u, int v) { int f1 = _top[u], f2 = _top[v]; long long ret = 1; while(f1 != f2) { if(depth[f1] < depth[f2]) { swap(f1, f2); swap(u, v); } ret = Mul(ret, Query(pos[f1], pos[u], 1, n, 1)); u = fa[f1]; f1 = _top[u]; } if(u == v) return ret; if(depth[u] > depth[v]) swap(u, v); ret = Mul(ret, Query(pos[son[u]], pos[v], 1, n, 1)); return ret; } int main() { while(cin>>n>>m) { init(); int u, v; long long w; for(int i=1; i<n; i++) { scanf("%d%d%lld", &u, &v, &w); AddEdge(u, v, w); edge_id[i] = edge_size - 1; edge_value[i] = w; AddEdge(v, u, w); } DFS(1, 0, 0); BuildTree(1, 1); for(int i=1; i<n; i++) { Edge e = edges[edge_id[i]]; if(depth[e.from] > depth[e.to]) edge_id[i] = pos[e.from]; else edge_id[i] = pos[e.to]; } BuildSegTree(1, n, 1); for(int i=1; i<n; i++) { Update(edge_id[i], edge_value[i], 1, n, 1); } for(int i=0; i<m; i++) { int op; scanf("%d", &op); if(op == 1) { scanf("%d%d%lld", &u, &v, &w); long long ans = Calc(u, v); if(ans == 0) puts("0"); else printf("%lld\n", w / ans); } else { scanf("%d%lld", &u, &w); Update(edge_id[u], w, 1, n, 1); } } } return 0; }