#include <bits/stdc++.h>
using namespace std;
const int mod = 20090717;
long long Mul(long long a, long long b) {
  if (a == 0 || b == 0) return 0;
  if (1e18 / a < b) return 0;
  return a * b;
}
class SegmentTree {
 public:
  struct Tree {
    int l, r;
    long long val;
  } t[200010 << 4];
  void pushup(int root) {
    t[root].val = Mul(t[root << 1].val, t[root << 1 | 1].val);
  }
  void build(int l, int r, int root) {
    t[root].l = l;
    t[root].r = r;
    if (l == r) {
      t[root].val = 0;
      return;
    }
    int mid = l + r >> 1;
    build(l, mid, root << 1);
    build(mid + 1, r, root << 1 | 1);
    pushup(root);
  }
  void update(int l, int r, long long val, int root) {
    if (l <= t[root].l && t[root].r <= r) {
      t[root].val = val;
      return;
    }
    int mid = t[root].l + t[root].r >> 1;
    if (l <= mid) update(l, r, val, root << 1);
    if (r > mid) update(l, r, val, root << 1 | 1);
    pushup(root);
  }
  long long query(int l, int r, int root) {
    if (l <= t[root].l && t[root].r <= r) return t[root].val;
    int mid = t[root].l + t[root].r >> 1;
    long long ans = 1;
    if (l <= mid) ans = Mul(ans, query(l, r, root << 1));
    if (r > mid) ans = Mul(ans, query(l, r, root << 1 | 1));
    return ans;
  }
} T;
struct Point {
  int from, to;
  long long val;
} p[200010];
struct Edge {
  int to, next;
} E[200010 << 1];
int head[200010], cnt, tot;
int top[200010], son[200010], size[200010], deep[200010], pa[200010],
    id[200010];
void init() {
  memset(head, -1, sizeof head);
  tot = cnt = 0;
}
void addedge(int u, int v) {
  E[cnt].to = v;
  E[cnt].next = head[u];
  head[u] = cnt++;
}
void dfs1(int u, int fa, int d) {
  size[u] = 1;
  deep[u] = d;
  son[u] = 0;
  for (int i = head[u]; ~i; i = E[i].next) {
    int v = E[i].to;
    if (v != fa) {
      dfs1(v, u, d + 1);
      pa[v] = u;
      size[u] += size[v];
      if (size[v] > size[son[u]]) son[u] = v;
    }
  }
}
void dfs2(int u, int first) {
  top[u] = first;
  id[u] = ++tot;
  if (son[u]) dfs2(son[u], first);
  for (int i = head[u]; ~i; i = E[i].next) {
    int v = E[i].to;
    if (v != pa[u] && v != son[u]) dfs2(v, v);
  }
}
long long Solve(int u, int v) {
  int x = top[u], y = top[v];
  long long ans = 1;
  while (x != y) {
    if (deep[x] < deep[y]) {
      swap(u, v);
      swap(x, y);
    }
    ans = Mul(ans, T.query(id[x], id[u], 1));
    u = pa[x];
    x = top[u];
  }
  if (deep[u] > deep[v]) swap(u, v);
  if (u != v) ans = Mul(ans, T.query(id[son[u]], id[v], 1));
  return ans;
}
inline void solve() {
  int n, m;
  scanf("%d%d", &n, &m);
  init();
  for (int i = 1; i < n; i++) {
    scanf("%d%d%I64d", &p[i].from, &p[i].to, &p[i].val);
    addedge(p[i].from, p[i].to);
    addedge(p[i].to, p[i].from);
  }
  dfs1(1, 0, 1);
  dfs2(1, 1);
  T.build(1, n, 1);
  for (int i = 1; i < n; i++) {
    if (deep[p[i].from] < deep[p[i].to]) swap(p[i].from, p[i].to);
    T.update(id[p[i].from], id[p[i].from], p[i].val, 1);
  }
  while (m--) {
    int op, a, b;
    long long x;
    scanf("%d", &op);
    if (op == 1) {
      scanf("%d%d%I64d", &a, &b, &x);
      long long res = Solve(a, b);
      if (res == 0)
        puts("0");
      else
        printf("%I64d\n", x / res);
    } else {
      scanf("%d%I64d", &a, &x);
      T.update(id[p[a].from], id[p[a].from], x, 1);
    }
  }
}
int main() {
  solve();
  return 0;
}
