#include <bits/stdc++.h>
using namespace std;
void show() { cout << '\n'; }
template <typename T, typename... Args>
void show(T a, Args... args) {
  cout << a << " ";
  show(args...);
}
template <typename T>
void show_c(T& a) {
  for (auto& x : a) {
    cout << x << " ";
  }
  cout << endl;
}
vector<int> out[400010];
long long cost[400010];
int n;
struct node {
  long long have;
  int left, right;
} tree[5 * 400010];
int pos[400010];
int mark[400010];
node merge(node x, node y) {
  node tmp;
  tmp.have = x.have * y.have;
  if (tmp.have / x.have != y.have) {
    tmp.have = LLONG_MAX;
  }
  tmp.left = x.left;
  tmp.right = y.right;
  return tmp;
}
void build(int num, int le, int ri) {
  tree[num].left = le;
  tree[num].right = ri;
  if (le == ri) {
    mark[le] = num;
    tree[num].have = cost[le];
  } else {
    build(2 * num, le, (le + ri) / 2);
    build(2 * num + 1, (le + ri) / 2 + 1, ri);
    tree[num] = merge(tree[2 * num], tree[2 * num + 1]);
  }
}
void update(int num, long long vv) {
  int pp = mark[pos[num]];
  tree[pp].have = vv;
  pp /= 2;
  while (pp) {
    tree[pp] = merge(tree[2 * pp], tree[2 * pp + 1]);
    pp /= 2;
  }
}
node get(int num, int ql, int qr) {
  if (ql <= tree[num].left && qr >= tree[num].right)
    return tree[num];
  else {
    bool lon = false, ron = false;
    if (ql <= tree[2 * num].right) lon = true;
    if (qr >= tree[2 * num + 1].left) ron = true;
    if (lon && ron) {
      return merge(get(2 * num, ql, qr), get(2 * num + 1, ql, qr));
    } else if (lon) {
      return get(2 * num, ql, qr);
    } else if (ron) {
      return get(2 * num + 1, ql, qr);
    }
  }
}
int chainNo[400010];
int chaincnt;
int chainLdr[400010];
int level[400010];
int childcnt[400010];
int parent[400010];
void dfs(int x, int p) {
  level[x] = level[p] + 1;
  childcnt[x] = 1;
  parent[x] = p;
  for (int i = 0; i < out[x].size(); ++i) {
    if (out[x][i] != p) {
      dfs(out[x][i], x);
      childcnt[x] += childcnt[out[x][i]];
    }
  }
}
int snow;
void HLD(int x, int cnt, bool start) {
  if (start) {
    chainLdr[cnt] = x;
  }
  chainNo[x] = cnt;
  pos[x] = ++snow;
  int mx = -1;
  for (int i = 0; i < out[x].size(); ++i) {
    if (out[x][i] != parent[x]) {
      if (mx == -1)
        mx = out[x][i];
      else if (childcnt[out[x][i]] > childcnt[mx]) {
        mx = out[x][i];
      }
    }
  }
  if (mx == -1) return;
  HLD(mx, cnt, false);
  for (int i = 0; i < out[x].size(); ++i) {
    if (out[x][i] != mx && out[x][i] != parent[x]) {
      HLD(out[x][i], ++chaincnt, true);
    }
  }
}
int lca(int x, int y) {
  while (chainNo[x] != chainNo[y]) {
    if (level[chainLdr[chainNo[x]]] > level[chainLdr[chainNo[y]]]) {
      x = parent[chainLdr[chainNo[x]]];
    } else {
      y = parent[chainLdr[chainNo[y]]];
    }
  }
  if (level[x] < level[y]) {
    return x;
  } else {
    return y;
  }
}
node query(int x, int u) {
  if (chainNo[x] != chainNo[u]) {
    return merge(get(1, pos[chainLdr[chainNo[x]]], pos[x]),
                 query(parent[chainLdr[chainNo[x]]], u));
  } else {
    return get(1, pos[u], pos[x]);
  }
}
void add_edge(int u, int v, int num) {
  out[u].push_back(n + num);
  out[n + num].push_back(u);
  out[v].push_back(n + num);
  out[n + num].push_back(v);
}
long long ini[400010];
int main() {
  int q;
  scanf("%d %d", &n, &q);
  int u, v;
  long long w;
  for (int i = 1; i < n; ++i) {
    scanf("%d %d %I64d", &u, &v, &w);
    add_edge(u, v, i);
    ini[n + i] = w;
  }
  for (int i = 1; i <= n; ++i) {
    ini[i] = 1;
  }
  dfs(1, 0);
  snow = 0;
  chaincnt = 0;
  HLD(1, ++chaincnt, true);
  for (int i = 1; i <= n + n - 1; ++i) {
    cost[pos[i]] = ini[i];
  }
  build(1, 1, n + n - 1);
  int type;
  long long val;
  while (q--) {
    scanf("%d", &type);
    if (type == 1) {
      scanf("%d %d %I64d", &u, &v, &val);
      int cca = lca(u, v);
      node shaon = merge(query(u, cca), query(v, cca));
      printf("%I64d\n", val / shaon.have);
    } else {
      scanf("%d %I64d", &u, &val);
      ini[n + u] = val;
      cost[pos[n + u]] = val;
      update(n + u, cost[pos[n + u]]);
    }
  }
  return 0;
}
