#include <bits/stdc++.h>
struct Edge {
  int32_t src, dst;
  int32_t index;
  Edge() {}
  Edge(int32_t src_, int32_t dst_, int32_t index_) {
    src = src_;
    dst = dst_;
    index = index_;
  }
};
int32_t time_ = 0;
void dfs(int32_t vertex, int32_t parent, std::vector<Edge>* graph,
         int32_t depth, int32_t* depths, int32_t* tin, int32_t* tout) {
  tin[vertex] = time_++;
  depths[vertex] = depth;
  for (int32_t i = 0; i < graph[vertex].size(); i++)
    if (graph[vertex][i].dst != parent)
      dfs(graph[vertex][i].dst, vertex, graph, depth + 1, depths, tin, tout);
  tout[vertex] = time_;
}
bool is_ancestor(int32_t v1, int32_t v2, int32_t* tin, int32_t* tout) {
  return tin[v1] <= tin[v2] && tout[v2] <= tout[v1];
}
void build_ancestors(int32_t vertex, int32_t parent, int32_t** ancestors,
                     std::vector<Edge>* graph) {
  ancestors[vertex] = new int32_t[20];
  ancestors[vertex][0] = 0;
  ancestors[vertex][1] = parent;
  for (int32_t i = 2; i < 20; i++) {
    if (ancestors[vertex][i - 1] == -1)
      ancestors[vertex][i] = -1;
    else
      ancestors[vertex][i] = ancestors[ancestors[vertex][i - 1]][i - 1];
  }
  for (int32_t i = 0; i < graph[vertex].size(); i++)
    if (graph[vertex][i].dst != parent)
      build_ancestors(graph[vertex][i].dst, vertex, ancestors, graph);
}
int32_t kth_ancestor(int32_t vertex, int32_t** ancestors, int32_t k) {
  if (k == 0) return vertex;
  if (k == 1) return ancestors[vertex][1];
  int32_t best_ind = 1;
  for (int32_t i = 2; i < 20; i++)
    if (k - (1 << (i - 1)) >= 0)
      best_ind = i;
    else
      break;
  return kth_ancestor(ancestors[vertex][best_ind], ancestors,
                      k - (1 << (best_ind - 1)));
}
int32_t lca(int32_t v1, int32_t v2, int32_t* tin, int32_t* tout,
            int32_t** ancestors) {
  if (is_ancestor(v1, v2, tin, tout)) return v1;
  if (is_ancestor(v2, v1, tin, tout)) return v2;
  for (int32_t i = 19; i >= 0; i--) {
    if (ancestors[v1][i] != -1 && !is_ancestor(ancestors[v1][i], v2, tin, tout))
      v1 = ancestors[v1][i];
  }
  return ancestors[v1][1];
}
int32_t* dsu_parents;
int32_t* dsu_top;
int32_t* depths;
int32_t find_root(int32_t vertex) {
  if (dsu_parents[vertex] == vertex) return vertex;
  return dsu_parents[vertex] = find_root(dsu_parents[vertex]);
}
bool join(int32_t v1, int32_t v2) {
  int32_t root1 = find_root(v1);
  int32_t root2 = find_root(v2);
  if (root1 == root2) return false;
  dsu_parents[root1] = root2;
  if (depths[dsu_top[root1]] < depths[dsu_top[root2]])
    dsu_top[root2] = dsu_top[root1];
  return true;
}
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  std::cout.tie(0);
  int32_t n, m;
  std::cin >> n >> m;
  std::vector<Edge>* graph = new std::vector<Edge>[n];
  int64_t* edge_weights = new int64_t[n - 1];
  Edge* edges = new Edge[n - 1];
  std::unordered_map<int64_t, int32_t> edges_map;
  edges_map.max_load_factor(0.25);
  edges_map.reserve(n - 1);
  for (int32_t i = 0; i < n - 1; i++) {
    int32_t src, dst;
    int64_t weight;
    std::cin >> src >> dst >> weight;
    src--;
    dst--;
    graph[src].emplace_back(src, dst, i);
    graph[dst].emplace_back(dst, src, i);
    edge_weights[i] = weight;
    edges[i] = {src, dst, i};
    edges_map[(int64_t)src * n + dst] = i;
    edges_map[(int64_t)dst * n + src] = i;
  }
  depths = new int32_t[n];
  int32_t *tin = new int32_t[n], *tout = new int32_t[n];
  dfs(0, -1, graph, 0, depths, tin, tout);
  int32_t** ancestors = new int32_t*[n];
  build_ancestors(0, -1, ancestors, graph);
  dsu_parents = new int32_t[n];
  dsu_top = new int32_t[n];
  for (int32_t i = 0; i < n; i++) {
    dsu_parents[i] = i;
    dsu_top[i] = i;
  }
  for (int32_t i = 0; i < n; i++) {
    std::vector<int32_t> neighbors_1;
    for (int32_t j = 0; j < graph[i].size(); j++)
      if (edge_weights[graph[i][j].index] == 1)
        neighbors_1.push_back(graph[i][j].dst);
    for (int32_t j = 0; j < neighbors_1.size(); j++) join(i, neighbors_1[j]);
  }
  for (int32_t q = 0; q < m; q++) {
    int32_t type;
    std::cin >> type;
    if (type == 1) {
      int32_t v1, v2;
      int64_t num;
      std::cin >> v1 >> v2 >> num;
      v1--;
      v2--;
      if (depths[v1] < depths[v2]) {
        int32_t tmp = v1;
        v1 = v2;
        v2 = tmp;
      }
      int32_t lca_cur = lca(v1, v2, tin, tout, ancestors);
      int32_t cur = v1;
      int32_t num_ancestor = -1;
      while (cur != v2) {
        if (num == 0) break;
        int32_t next_dir = num_ancestor == -1
                               ? ancestors[cur][1]
                               : kth_ancestor(v2, ancestors, num_ancestor - 1);
        int32_t next_edge = edges_map[(int64_t)cur * n + next_dir];
        num /= edge_weights[next_edge];
        if (num_ancestor == -1) {
          cur = dsu_top[find_root(next_dir)];
          if (depths[dsu_top[find_root(next_dir)]] <= depths[lca_cur])
            num_ancestor = depths[v2] - depths[cur];
        } else {
          int32_t num_ancestor_cur = 0;
          int32_t cur2 = v2;
          for (int32_t i = 19; i > 0; i--) {
            if (ancestors[cur2][i] != -1 &&
                depths[ancestors[cur2][i]] >= depths[dsu_top[find_root(cur)]] &&
                find_root(ancestors[cur2][i]) != find_root(cur)) {
              num_ancestor_cur += 1 << (i - 1);
              cur2 = ancestors[cur2][i];
            }
          }
          num_ancestor_cur++;
          num_ancestor = num_ancestor_cur;
          int32_t next = kth_ancestor(v2, ancestors, num_ancestor);
          if (depths[next] < depths[next_dir]) {
            num_ancestor--;
            next = next_dir;
          }
          cur = next;
        }
      }
      std::cout << num << "\n";
    } else {
      int32_t ind;
      int64_t new_val;
      std::cin >> ind >> new_val;
      ind--;
      edge_weights[ind] = new_val;
      if (new_val == 1) {
        join(edges[ind].src, edges[ind].dst);
      }
    }
  }
  return 0;
}
