#include <bits/stdc++.h>
using namespace std;
struct segnode {
  int start, fin;
  long long val;
  segnode *leftchild, *rightchild;
  segnode() {
    leftchild = 0;
    rightchild = 0;
  }
  segnode(int nstart, int nfin, long long nval) : segnode() {
    start = nstart;
    fin = nfin;
    val = nval;
  }
  static long long op(long long l, long long r) {
    if (1000000000000000001 / l < r) return 1000000000000000001;
    return l * r;
  }
  static long long nullvalue() { return 1; }
  void update() {
    val = 1;
    if (leftchild != 0) val = op(val, leftchild->val);
    if (rightchild != 0) val = op(val, rightchild->val);
  }
};
template <class T>
struct segtree {
  vector<T> node;
  void addnode(int start, int fin, long long val) {
    node.push_back(T(start, fin, val));
  }
  void initialize() {
    node.reserve(node.size() * 2 + 100);
    int cl = 0, cr = node.size();
    while (cr - cl > 1) {
      int nl = cr, nr = cr;
      for (int i = cl; i < cr; i += 2) {
        node.push_back(T(node[i].start, node[i].fin, 1));
        node[nr].leftchild = &node[i];
        if (i + 1 < cr) {
          node[nr].fin = node[i + 1].fin;
          node[nr].rightchild = &node[i + 1];
        }
        node[nr].update();
        nr++;
      }
      cl = nl;
      cr = nr;
    }
  }
  long long getRange(int l, int r, T* curnode = 0) {
    if (curnode == 0) curnode = &node.back();
    if (curnode->fin <= l || curnode->start >= r) return T::nullvalue();
    if (curnode->start >= l && curnode->fin <= r) return curnode->val;
    long long ret = T::nullvalue();
    if (curnode->leftchild != 0)
      ret = T::op(ret, getRange(l, r, curnode->leftchild));
    if (curnode->rightchild != 0)
      ret = T::op(ret, getRange(l, r, curnode->rightchild));
    return ret;
  }
  void updatePos(int pos, long long nval, T* curnode = 0) {
    if (curnode == 0) curnode = &node.back();
    if (pos < curnode->start || pos >= curnode->fin) return;
    if (curnode->fin - curnode->start == 1) {
      curnode->val = nval;
      return;
    }
    if (curnode->leftchild != 0) updatePos(pos, nval, curnode->leftchild);
    if (curnode->rightchild != 0) updatePos(pos, nval, curnode->rightchild);
    curnode->update();
  }
};
template <int N>
struct tree {
  vector<pair<int, int> > conn[N];
  int nedges;
  long long edgex[N];
  pair<int, int> edge[N];
  tree() { nedges = 0; }
  void addEdge(int a, int b, long long val) {
    conn[a].push_back(make_pair(b, nedges));
    conn[b].push_back(make_pair(a, nedges));
    edge[nedges] = make_pair(a, b);
    edgex[nedges++] = val;
  }
  int depth[N], parent[N][20], paredge[N], subsize[N];
  int init(int pos = 0, int prev = -1, int preve = -1, int curdepth = 0) {
    depth[pos] = curdepth;
    paredge[pos] = preve;
    parent[pos][0] = prev;
    if (preve != -1 && pos == edge[preve].first)
      swap(edge[preve].first, edge[preve].second);
    for (int i = 1; i < 20; i++) {
      if (parent[pos][i - 1] != -1)
        parent[pos][i] = parent[parent[pos][i - 1]][i - 1];
      else
        parent[pos][i] = -1;
    }
    subsize[pos] = 1;
    for (auto next : conn[pos])
      if (next.first != prev)
        subsize[pos] += init(next.first, pos, next.second, curdepth + 1);
    return subsize[pos];
  }
  segtree<segnode> st[N];
  int segparent[N], segind[N];
  void seginit(int pos = 0, int prev = -1) {
    segparent[pos] = pos;
    segind[pos] = 0;
    if (prev != -1) {
      if (subsize[parent[pos][0]] < subsize[pos] * 2) {
        segparent[pos] = segparent[parent[pos][0]];
        segind[pos] = segind[parent[pos][0]] + 1;
        st[segparent[pos]].addnode(segind[pos] - 1, segind[pos],
                                   edgex[paredge[pos]]);
      }
    }
    for (auto next : conn[pos])
      if (next.first != prev) seginit(next.first, pos);
    if (segparent[pos] == pos && st[pos].node.size() != 0) st[pos].initialize();
  }
  int getanc(int a, int b) {
    if (depth[b] > depth[a]) swap(a, b);
    for (int tpow = 19; tpow >= 0; tpow--)
      if (depth[a] - (1 << tpow) >= depth[b]) a = parent[a][tpow];
    for (int tpow = 19; tpow >= 0; tpow--)
      if (parent[a][tpow] != parent[b][tpow]) {
        a = parent[a][tpow];
        b = parent[b][tpow];
      }
    if (a == b) return a;
    return parent[a][0];
  }
  long long moveup(int pos, int dest) {
    if (pos == dest) return segnode::nullvalue();
    if (segparent[pos] == segparent[dest])
      return st[segparent[pos]].getRange(segind[dest], segind[pos]);
    if (segparent[pos] != pos)
      return segnode::op(st[segparent[pos]].getRange(0, segind[pos]),
                         moveup(segparent[pos], dest));
    return segnode::op(edgex[paredge[pos]], moveup(parent[pos][0], dest));
  }
  long long getUp(int a, int b) {
    int anc = getanc(a, b);
    return segnode::op(moveup(a, anc), moveup(b, anc));
  }
  void update(int ind, long long nval) {
    edgex[ind] = nval;
    int a = edge[ind].first, b = edge[ind].second;
    if (segparent[a] == segparent[b])
      st[segparent[a]].updatePos(segind[a], nval);
  }
};
tree<200000> t;
int n, m, p1, p2;
long long p3;
int main() {
  cin.sync_with_stdio(false);
  cin >> n >> m;
  for (int i = 0; i < n - 1; i++) {
    cin >> p1 >> p2 >> p3;
    t.addEdge(p1 - 1, p2 - 1, p3);
  }
  t.init();
  t.seginit();
  for (int i = 0; i < m; i++) {
    cin >> p1;
    if (p1 == 1) {
      cin >> p1 >> p2 >> p3;
      cout << p3 / t.getUp(p1 - 1, p2 - 1) << '\n';
    } else {
      cin >> p2 >> p3;
      t.update(p2 - 1, p3);
    }
  }
  return 0;
}
