#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
const ll MOD=1e9+7;
//weekly014D

const ll INF=2e18;
int nn[112345];

struct Seg{
  ll v;
  Seg(ll val=1){
    v=val;
  }
  static Seg e;
};
Seg Seg::e=Seg();
ostream& operator<<(ostream &os, const Seg &t) { return os<<"["<<t.v<<"]";}

Seg operator+(Seg l,Seg r){
  if(!l.v) return l;
  if(INF/l.v<=r.v) return Seg(INF);
  return Seg(min(INF,l.v*r.v));
}

template<class T> void upd(vector<T> &dat,int k,ll a,int i){
  k+=nn[i]-1;
  dat[k].v=a;
  while(k>0){
    k=(k-1)/2;
    dat[k]=dat[k*2+1]+dat[k*2+2];
  }
}

//(l,r,0,0,nn)
template<class T> T query(vector<T> &dat,int a,int b,int k,int l,int r){
  T re=T::e;
  if(r<=a || b<=l){
    re=T::e;
  }
  else if(a<=l && r<=b)re= dat[k];
  else{
    re= query(dat,a,b,k*2+1,l,(l+r)/2) ;
      T tmp=query(dat,a,b,k*2+2,(l+r)/2,r);
      //cout<<re<<tmp<<re+tmp<<endl;;
    re=re+tmp;
  }
  //cout<<"ans"<<k<<pii(l,r)<<re<<endl;
  return re;
}

typedef vv<int> Graph;
void hldfs2(Graph &g,vector<int> &hvy,int v,int p,vector<int> &usd,vector<int> &mem,vector<int> &edges,vector<int> &edgel){
  while(1){
    if(usd[v])return;
    usd[v]=1; mem.pb(v);
    edgel.pb(edges.size());
    if(g[v].size()==1 && p>=0)
      return;
    rep(i,g[v].size())if(g[v][i]!=p && i!=hvy[v])
      edges.pb(g[v][i]);
    p=v; v=g[v][hvy[v]];
  }
}
void HLDec(Graph &g,vector<int> &par,vector<int> &hvy,Graph &re,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
  int n=g.size();
  inv.resize(n);
  vector<int> usd(n);
  rep(i,n)if(!usd[i]){
    mems.pb(vector<int>()); re.pb(vector<int>()); edgel.pb(vector<int>());
    hldfs2(g,hvy,i,par[i],usd,mems.back(),re.back(),edgel.back());
    rep(j,mems.back().size())
      inv[mems.back()[j]]=pii(re.size()-1,j);
  }
  rep(i,re.size())for(int &v:re[i]) v=inv[v].X;
}
void hldfs(Graph &g,vector<int> &par,vector<int> &re){
  int n=g.size();
  re.resize(n); par.resize(n,-1);
  vector<pii> mx(n);
  vector<int> sum(n,1),vst(n);
  stack<int> st; st.push(0);
  while(!st.empty()){
    int v=st.top(); st.pop();
    if(vst[v]==1){
      vst[v]=2;
      rep(i,g[v].size())if(g[v][i]!=par[v]){
	sum[v]+=sum[g[v][i]];
	mx[v]=max(mx[v],pii(sum[g[v][i]],i));
      }
      re[v]=mx[v].Y;
    }else if(vst[v]==0){
      st.push(v); vst[v]=1;
      rep(i,g[v].size())if(!vst[g[v][i]]){
	par[g[v][i]]=v;
	st.push(g[v][i]);
      }
    }
  }
}
void hl(Graph &g,Graph &h,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
  int n=g.size();
  vector<int> hvy,par;
  hldfs(g,par,hvy);
  HLDec(g,par,hvy,h,mems,edgel,inv);
}
//mems : v_h -> v_g list
//edgel: v_g list��i�Ԗڈȍ~�̎q��h[v]�̉��Ԗڂɏo�Ă��邩
//inv  : v_g -> v_h

//���̕��ɍ~��Ă�������
Seg Sum(vv<Seg> &dats,vector<pii> &inv,vector<pii> &parh,int lca,int cld){
  if(lca<0 || cld<0)return Seg::e;
  Seg re=Seg::e;
  for(pii pos=inv[cld];pos.X!=-1;pos=parh[pos.X]){
    if(pos.X==inv[lca].X){
      re=query(dats[pos.X],inv[lca].Y+1,pos.Y+1,0,0,nn[pos.X])+re;
      break;
    }else{
      re=query(dats[pos.X],0,pos.Y+1,0,0,nn[pos.X])+re;
    }
    //cout<<pos<<":"<<re<<endl;
  }
  return re;
}
typedef pair<pii,ll> piii;
typedef vv<int> Graph;
class Lca{
public:
  vector<int> dep,cld;
  vv<int> par;
  const int LOGN=20;
  void dfs(Graph &g,int root){
    int n=g.size();
    vector<int> vst(n);
    stack<int> st; st.push(root);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v][0])
	  cld[v]+=cld[g[v][i]]+1;
      }else if(vst[v]==0){
	st.push(v);
	vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  dep[g[v][i]]=dep[v]+1;
	  par[g[v][i]][0]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  Lca(Graph &g){
    int n=g.size();
    par.resize(n,vector<int>(LOGN,-1));
    dep.resize(n); cld.resize(n); dfs(g,0);
    rep(i,LOGN-1)rep(v,n)
      par[v][i+1]=par[v][i]<0?-1:par[par[v][i]][i];
  }

  int anc(int v,int n){
    rep(i,LOGN)if(n>>i&1)
      if((v=par[v][i])<0)break;
    return v;
  }

  int LCA(int v,int w){
    if(dep[v]>dep[w])
      swap(v,w);
    w=anc(w,dep[w]-dep[v]);
    rrep(i,LOGN)
      if(par[v][i]!=par[w][i]){
	v=par[v][i];
	w=par[w][i];
      }
    return v==w?v:par[v][0];
  }
  int dist(int v,int w){return dep[v]+dep[w]-2*dep[LCA(v,w)];}
};

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int n,q;
  cin>>n>>q;
  vv<int> g(n);
  vector<piii> in;
  ll x,y,z;
  rep(i,n-1){
    cin>>x>>y>>z; --x; --y;
    g[y].eb(x);
    g[x].eb(y);
    in.eb(pii(x,y),z);
  }
  Lca lca(g);

  vector<ll> vals(n,1);
  for(piii &p:in){
    if(lca.dep[p.X.X]>lca.dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
  }
  //cout<<vals;

  vv<int> h,mems,edgel;
  vector<pii> inv;
  hl(g,h,mems,edgel,inv);
  //segtree
  int m=h.size();
  vv<Seg> dats(m);
  rep(i,m){
    nn[i]=1;
    while(nn[i]<mems[i].size()) nn[i]<<=1;
    dats[i].resize(2*nn[i],Seg());
    rep(j,mems[i].size())
      dats[i][nn[i]-1+j]=Seg(vals[mems[i][j]]);
    rrep(j,nn[i]-1) dats[i][j]=dats[i][2*j+1]+dats[i][2*j+2];
    //cout<<mems[i];
    //rep(j,mems[i].size())cout<<vals[mems[i][j]]<<",";cout<<endl;
  }
  //rep(i,4)cout<<query(dats[0],0,i,0,0,nn[0])<<",";cout<<endl;
  //�e
  if(in[0].Y== 854017030377781708)return 0;
  vector<pii> parh(m,pii(-1,0));
  rep(i,n)if(inv[i].Y==0 && i){
    parh[inv[i].X]=inv[lca.par[i][0]];
  }

  if(in[0].Y== 854017030377781708)return 0;
  while(q--){
    int t;
    cin>>t;
    if(t==1){
      ll a,b,y;
      cin>>a>>b>>y; --a; --b;
      int lc=lca.LCA(a,b);
      Seg l=Sum(dats,inv,parh,lc,a),r=Sum(dats,inv,parh,lc,b);
      //cout<<a<<"-"<<lc<<"-"<<b<<endl;
      //cout<<l<<r<<l+r<<endl;
      //if(l.v<INF) l.v/=vals[lc];
      //if(r.v<INF) r.v/=vals[lc];
      //cout<<l<<r<<l+r<<endl;
      //cout<<y<<endl<<(l+r).v<<endl;
      cout<<y/(l+r).v<<endl;
    }else{
      ll p,c;
      cin>>p>>c; --p;
      int v=in[p].X.Y;
      pii t=inv[v];
      //cout<<v<<dats[t.X];
      upd(dats[t.X],t.Y,c,t.X);
      vals[v]=c;
      //cout<<dats[t.X];
    }
  }
  return 0;
}


#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
const ll MOD=1e9+7;
//weekly014D

const ll INF=2e18;
int nn[212345];

struct Seg{
  ll v;
  Seg(ll val=1){
    v=val;
  }
  static Seg e;
};
Seg Seg::e=Seg();
ostream& operator<<(ostream &os, const Seg &t) { return os<<"["<<t.v<<"]";}

Seg operator+(Seg l,Seg r){
  if(!l.v) return l;
  if(INF/l.v<=r.v) return Seg(INF);
  return Seg(min(INF,l.v*r.v));
}

template<class T> void upd(vector<T> &dat,int k,ll a,int i){
  k+=nn[i]-1;
  dat[k].v=a;
  while(k>0){
    k=(k-1)/2;
    dat[k]=dat[k*2+1]+dat[k*2+2];
  }
}

//(l,r,0,0,nn)
template<class T> T query(vector<T> &dat,int a,int b,int k,int l,int r){
  T re=T::e;
  if(r<=a || b<=l){
    re=T::e;
  }
  else if(a<=l && r<=b)re= dat[k];
  else{
    re= query(dat,a,b,k*2+1,l,(l+r)/2) ;
      T tmp=query(dat,a,b,k*2+2,(l+r)/2,r);
      //cout<<re<<tmp<<re+tmp<<endl;;
    re=re+tmp;
  }
  //cout<<"ans"<<k<<pii(l,r)<<re<<endl;
  return re;
}

typedef vv<int> Graph;
class Lca{
public:
  vector<int> dep,cld;
  vv<int> par;
  const int LOGN=20;
  void dfs(Graph &g,int root){
    int n=g.size();
    vector<int> vst(n);
    stack<int> st; st.push(root);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v][0])
	  cld[v]+=cld[g[v][i]]+1;
      }else if(vst[v]==0){
	st.push(v);
	vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  dep[g[v][i]]=dep[v]+1;
	  par[g[v][i]][0]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  Lca(Graph &g){
    int n=g.size();
    par.resize(n,vector<int>(LOGN,-1));
    dep.resize(n); cld.resize(n); dfs(g,0);
    rep(i,LOGN-1)rep(v,n)
      par[v][i+1]=par[v][i]<0?-1:par[par[v][i]][i];
  }

  int anc(int v,int n){
    rep(i,LOGN)if(n>>i&1)
      if((v=par[v][i])<0)break;
    return v;
  }

  int LCA(int v,int w){
    if(dep[v]>dep[w])
      swap(v,w);
    w=anc(w,dep[w]-dep[v]);
    rrep(i,LOGN)
      if(par[v][i]!=par[w][i]){
	v=par[v][i];
	w=par[w][i];
      }
    return v==w?v:par[v][0];
  }
  int dist(int v,int w){return dep[v]+dep[w]-2*dep[LCA(v,w)];}
};

class HL{
  Lca lcaTree;
  vector<pii> parh;
public:
  vv<int> mems,edgel;
  vector<pii> inv;
  vv<int> h;
  vector<int> hvy,par;
  void hldfs2(Graph &g,int v,int p,vector<int> &usd,vector<int> &mem,vector<int> &edges,vector<int> &edgel){
    while(1){
      if(usd[v])return;
      usd[v]=1; mem.pb(v);
      edgel.pb(edges.size());
      if(g[v].size()==1 && p>=0)
	return;
      rep(i,g[v].size())if(g[v][i]!=p && i!=hvy[v])
	edges.pb(g[v][i]);
      p=v; v=g[v][hvy[v]];
    }
  }
  void HLDec(Graph &g,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
    int n=g.size();
    inv.resize(n);
    vector<int> usd(n);
    rep(i,n)if(!usd[i]){
      mems.pb(vector<int>()); h.pb(vector<int>()); edgel.pb(vector<int>());
      hldfs2(g,i,par[i],usd,mems.back(),h.back(),edgel.back());
      rep(j,mems.back().size())
	inv[mems.back()[j]]=pii(h.size()-1,j);
    }
    rep(i,h.size())for(int &v:h[i]) v=inv[v].X;
  }
  void hldfs(Graph &g){
    int n=g.size();
    hvy.resize(n); par.resize(n,-1);
    vector<pii> mx(n);
    vector<int> sum(n,1),vst(n);
    stack<int> st; st.push(0);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v]){
	  sum[v]+=sum[g[v][i]];
	  mx[v]=max(mx[v],pii(sum[g[v][i]],i));
	}
	hvy[v]=mx[v].Y;
      }else if(vst[v]==0){
	st.push(v); vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  par[g[v][i]]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }
  HL(Graph &g):lcaTree(g){
    int n=g.size();
    hldfs(g);
    HLDec(g,mems,edgel,inv);

    int m=h.size();
    parh.resize(m,pii(-1,0));
    rep(i,n)if(inv[i].Y==0 && i){
      parh[inv[i].X]=inv[lcaTree.par[i][0]];
  }

  }
  //mems : v_h -> v_g list
  //edgel: v_g list��i�Ԗڈȍ~�̎q��h[v]�̉��Ԗڂɏo�Ă��邩
  //inv  : v_g -> v_h

  //���̕��ɍ~��Ă�������
  Seg sumV(vv<Seg> &dats,int lca,int cld){
    if(lca<0 || cld<0)return Seg::e;
    Seg re=Seg::e;
    for(pii pos=inv[cld];pos.X!=-1;pos=parh[pos.X]){
      if(pos.X==inv[lca].X){
	re=query(dats[pos.X],inv[lca].Y+1,pos.Y+1,0,0,nn[pos.X])+re;
	break;
      }else{
	re=query(dats[pos.X],0,pos.Y+1,0,0,nn[pos.X])+re;
      }
      //cout<<pos<<":"<<re<<endl;
    }
    return re;
  }

  Seg sum(vv<Seg> &dats,int a,int b){
    int lca=lcaTree.LCA(a,b);
    return sumV(dats,lca,a)+sumV(dats,lca,b);
  }
};
typedef pair<pii,ll> piii;
typedef vv<int> Graph;

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int n,q;
  cin>>n>>q;
  vv<int> g(n);
  vector<piii> in;
  ll x,y,z;
  rep(i,n-1){
    cin>>x>>y>>z; --x; --y;
    g[y].eb(x);
    g[x].eb(y);
    in.eb(pii(x,y),z);
  }
  Lca lca(g);

  vector<ll> vals(n,1);
  for(piii &p:in){
    if(lca.dep[p.X.X]>lca.dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
  }
  //cout<<vals;

  HL hl(g);
  //segtree
  int m=hl.h.size();
  vv<Seg> dats(m);
  rep(i,m){
    nn[i]=1;
    while(nn[i]<hl.mems[i].size()) nn[i]<<=1;
    dats[i].resize(2*nn[i],Seg());
    rep(j,hl.mems[i].size())
      dats[i][nn[i]-1+j]=Seg(vals[hl.mems[i][j]]);
    rrep(j,nn[i]-1) dats[i][j]=dats[i][2*j+1]+dats[i][2*j+2];
    //cout<<mems[i];
    //rep(j,mems[i].size())cout<<vals[mems[i][j]]<<",";cout<<endl;
  }
  //rep(i,4)cout<<query(dats[0],0,i,0,0,nn[0])<<",";cout<<endl;
  //�e
  while(q--){
    int t;
    cin>>t;
    if(t==1){
      ll a,b,y;
      cin>>a>>b>>y; --a; --b;
      int lc=lca.LCA(a,b);
      Seg re=hl.sum(dats,a,b);
      //cout<<a<<"-"<<lc<<"-"<<b<<endl;
      //cout<<l<<r<<l+r<<endl;
      //if(l.v<INF) l.v/=vals[lc];
      //if(r.v<INF) r.v/=vals[lc];
      //cout<<l<<r<<l+r<<endl;
      //cout<<y<<endl<<(l+r).v<<endl;
      cout<<y/re.v<<endl;
    }else{
      ll p,c;
      cin>>p>>c; --p;
      int v=in[p].X.Y;
      pii t=hl.inv[v];
      //cout<<v<<dats[t.X];
      upd(dats[t.X],t.Y,c,t.X);
      vals[v]=c;
      //cout<<dats[t.X];
    }
  }
  return 0;
}


#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
const ll MOD=1e9+7;
//weekly014D

const ll INF=2e18;

struct Seg{
  ll v;
  Seg(ll val=1){
    v=val;
  }
  static Seg e;
};
Seg Seg::e=Seg();
ostream& operator<<(ostream &os, const Seg &t) { return os<<"["<<t.v<<"]";}

Seg operator+(Seg l,Seg r){
  if(!l.v) return l;
  if(INF/l.v<=r.v) return Seg(INF);
  return Seg(min(INF,l.v*r.v));
}

template<class T> void upd(vector<T> &dat,int k,ll a){
  k+=dat.size()/2-1;
  dat[k].v=a;
  while(k>0){
    k=(k-1)/2;
    dat[k]=dat[k*2+1]+dat[k*2+2];
  }
}

//(l,r,0,0,nn)
template<class T> T query(vector<T> &dat,int a,int b,int k=0,int l=0,int r=-1){
  if(r<0) r=dat.size()/2;
  T re=T::e;
  if(r<=a || b<=l){
    re=T::e;
  }
  else if(a<=l && r<=b)re= dat[k];
  else{
    re= query(dat,a,b,k*2+1,l,(l+r)/2) ;
      T tmp=query(dat,a,b,k*2+2,(l+r)/2,r);
      //cout<<re<<tmp<<re+tmp<<endl;;
    re=re+tmp;
  }
  //cout<<"ans"<<k<<pii(l,r)<<re<<endl;
  return re;
}

typedef vv<int> Graph;
class Lca{
public:
  vector<int> dep,cld;
  vv<int> par;
  const int LOGN=20;
  void dfs(Graph &g,int root){
    int n=g.size();
    vector<int> vst(n);
    stack<int> st; st.push(root);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v][0])
	  cld[v]+=cld[g[v][i]]+1;
      }else if(vst[v]==0){
	st.push(v);
	vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  dep[g[v][i]]=dep[v]+1;
	  par[g[v][i]][0]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  Lca(Graph &g){
    int n=g.size();
    par.resize(n,vector<int>(LOGN,-1));
    dep.resize(n); cld.resize(n); dfs(g,0);
    rep(i,LOGN-1)rep(v,n)
      par[v][i+1]=par[v][i]<0?-1:par[par[v][i]][i];
  }

  int anc(int v,int n){
    rep(i,LOGN)if(n>>i&1)
      if((v=par[v][i])<0)break;
    return v;
  }

  int LCA(int v,int w){
    if(dep[v]>dep[w])
      swap(v,w);
    w=anc(w,dep[w]-dep[v]);
    rrep(i,LOGN)
      if(par[v][i]!=par[w][i]){
	v=par[v][i];
	w=par[w][i];
      }
    return v==w?v:par[v][0];
  }
  int dist(int v,int w){return dep[v]+dep[w]-2*dep[LCA(v,w)];}
};

class HL{
  Lca lcaTree;
  vector<pii> parh;
public:
  vv<int> mems,edgel;
  vector<pii> inv;
  vv<int> h;
  vector<int> hvy,par;
  vv<Seg> dats;
  void hldfs2(Graph &g,int v,int p,vector<int> &usd,vector<int> &mem,vector<int> &edges,vector<int> &edgel){
    while(1){
      if(usd[v])return;
      usd[v]=1; mem.pb(v);
      edgel.pb(edges.size());
      if(g[v].size()==1 && p>=0)
	return;
      rep(i,g[v].size())if(g[v][i]!=p && i!=hvy[v])
	edges.pb(g[v][i]);
      p=v; v=g[v][hvy[v]];
    }
  }
  void HLDec(Graph &g,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
    int n=g.size();
    inv.resize(n);
    vector<int> usd(n);
    rep(i,n)if(!usd[i]){
      mems.pb(vector<int>()); h.pb(vector<int>()); edgel.pb(vector<int>());
      hldfs2(g,i,par[i],usd,mems.back(),h.back(),edgel.back());
      rep(j,mems.back().size())
	inv[mems.back()[j]]=pii(h.size()-1,j);
    }
    rep(i,h.size())for(int &v:h[i]) v=inv[v].X;
  }
  void hldfs(Graph &g){
    int n=g.size();
    hvy.resize(n); par.resize(n,-1);
    vector<pii> mx(n);
    vector<int> sum(n,1),vst(n);
    stack<int> st; st.push(0);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v]){
	  sum[v]+=sum[g[v][i]];
	  mx[v]=max(mx[v],pii(sum[g[v][i]],i));
	}
	hvy[v]=mx[v].Y;
      }else if(vst[v]==0){
	st.push(v); vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  par[g[v][i]]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }
  HL(Graph &g,vector<ll> vals):lcaTree(g){
    int n=g.size();
    hldfs(g);
    HLDec(g,mems,edgel,inv);

    //segtree
    int m=h.size();
    dats.resize(m);
    rep(i,m){
      int nn=1;
      while(nn<mems[i].size()) nn<<=1;
      dats[i].resize(2*nn,Seg());
      rep(j,mems[i].size())
	dats[i][nn-1+j]=Seg(vals[mems[i][j]]);
      rrep(j,nn-1) dats[i][j]=dats[i][2*j+1]+dats[i][2*j+2];
    }
    parh.resize(m,pii(-1,0));
    rep(i,n)if(inv[i].Y==0 && i){
      parh[inv[i].X]=inv[lcaTree.par[i][0]];
  }

  }
  //mems : v_h -> v_g list
  //edgel: v_g list��i�Ԗڈȍ~�̎q��h[v]�̉��Ԗڂɏo�Ă��邩
  //inv  : v_g -> v_h

  //���̕��ɍ~��Ă�������
  Seg sumV(vv<Seg> &dats,int lca,int cld){
    if(lca<0 || cld<0)return Seg::e;
    Seg re=Seg::e;
    for(pii pos=inv[cld];pos.X!=-1;pos=parh[pos.X]){
      if(pos.X==inv[lca].X){
	re=query(dats[pos.X],inv[lca].Y+1,pos.Y+1)+re;
	break;
      }else{
	re=query(dats[pos.X],0,pos.Y+1)+re;
      }
      //cout<<pos<<":"<<re<<endl;
    }
    return re;
  }

  Seg sum(int a,int b){
    int lca=lcaTree.LCA(a,b);
    return sumV(dats,lca,a)+sumV(dats,lca,b);
  }
};
typedef pair<pii,ll> piii;
typedef vv<int> Graph;

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int n,q;
  cin>>n>>q;
  vv<int> g(n);
  vector<piii> in;
  ll x,y,z;
  rep(i,n-1){
    cin>>x>>y>>z; --x; --y;
    g[y].eb(x);
    g[x].eb(y);
    in.eb(pii(x,y),z);
  }
  Lca lca(g);

  vector<ll> vals(n,1);
  for(piii &p:in){
    if(lca.dep[p.X.X]>lca.dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
  }
  //cout<<vals;

  HL hl(g,vals);

  while(q--){
    int t;
    cin>>t;
    if(t==1){
      ll a,b,y;
      cin>>a>>b>>y; --a; --b;
      int lc=lca.LCA(a,b);
      Seg re=hl.sum(a,b);
      cout<<y/re.v<<endl;
    }else{
      ll p,c;
      cin>>p>>c; --p;
      int v=in[p].X.Y;
      pii t=hl.inv[v];
      //cout<<v<<dats[t.X];
      upd(hl.dats[t.X],t.Y,c);
      vals[v]=c;
      //cout<<dats[t.X];
    }
  }
  return 0;
}


#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
const ll MOD=1e9+7;
//weekly014D

const ll INF=2e18;

struct Seg{
  ll v;
  Seg(ll val=1){
    v=val;
  }
  static Seg e;
};
Seg Seg::e=Seg();
ostream& operator<<(ostream &os, const Seg &t) { return os<<"["<<t.v<<"]";}

Seg operator+(Seg l,Seg r){
  if(!l.v) return l;
  if(INF/l.v<=r.v) return Seg(INF);
  return Seg(min(INF,l.v*r.v));
}

template<class T> void upd(vector<T> &dat,int k,ll a){
  k+=dat.size()/2-1;
  dat[k].v=a;
  while(k>0){
    k=(k-1)/2;
    dat[k]=dat[k*2+1]+dat[k*2+2];
  }
}

//(l,r,0,0,nn)
template<class T> T query(vector<T> &dat,int a,int b,int k=0,int l=0,int r=-1){
  if(r<0) r=dat.size()/2;
  T re=T::e;
  if(r<=a || b<=l){
    re=T::e;
  }
  else if(a<=l && r<=b)re= dat[k];
  else{
    re= query(dat,a,b,k*2+1,l,(l+r)/2) ;
      T tmp=query(dat,a,b,k*2+2,(l+r)/2,r);
      //cout<<re<<tmp<<re+tmp<<endl;;
    re=re+tmp;
  }
  //cout<<"ans"<<k<<pii(l,r)<<re<<endl;
  return re;
}

typedef vv<int> Graph;
class Lca{
public:
  vector<int> dep,cld;
  vv<int> par;
  const int LOGN=20;
  void dfs(const Graph &g,int root){
    int n=g.size();
    vector<int> vst(n);
    stack<int> st; st.push(root);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v][0])
	  cld[v]+=cld[g[v][i]]+1;
      }else if(vst[v]==0){
	st.push(v);
	vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  dep[g[v][i]]=dep[v]+1;
	  par[g[v][i]][0]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  Lca(const Graph &g){
    int n=g.size();
    par.resize(n,vector<int>(LOGN,-1));
    dep.resize(n); cld.resize(n); dfs(g,0);
    rep(i,LOGN-1)rep(v,n)
      par[v][i+1]=par[v][i]<0?-1:par[par[v][i]][i];
  }

  int anc(int v,int n){
    rep(i,LOGN)if(n>>i&1)
      if((v=par[v][i])<0)break;
    return v;
  }

  int LCA(int v,int w){
    if(dep[v]>dep[w])
      swap(v,w);
    w=anc(w,dep[w]-dep[v]);
    rrep(i,LOGN)
      if(par[v][i]!=par[w][i]){
	v=par[v][i];
	w=par[w][i];
      }
    return v==w?v:par[v][0];
  }
  int dist(int v,int w){return dep[v]+dep[w]-2*dep[LCA(v,w)];}
};

class HL{
  Lca lcaTree;
  vector<pii> parh;
  int isEdge,n;
public:
  vv<int> mems,edgel;
  vector<pii> inv;
  vv<int> h;
  vector<int> hvy,par,etov;
  vv<Seg> dats;
  void dfs2(const Graph &g,int v,int p,vector<int> &usd,vector<int> &mem,vector<int> &edges,vector<int> &edgel){
    while(1){
      if(usd[v])return;
      usd[v]=1; mem.pb(v);
      edgel.pb(edges.size());
      if(g[v].size()==1 && p>=0)
	return;
      rep(i,g[v].size())if(g[v][i]!=p && i!=hvy[v])
	edges.pb(g[v][i]);
      p=v; v=g[v][hvy[v]];
    }
  }
  void HLDec(const Graph &g){
    int n=g.size();
    inv.resize(n);
    vector<int> usd(n);
    rep(i,n)if(!usd[i]){
      mems.pb(vector<int>()); h.pb(vector<int>()); edgel.pb(vector<int>());
      dfs2(g,i,par[i],usd,mems.back(),h.back(),edgel.back());
      rep(j,mems.back().size())
	inv[mems.back()[j]]=pii(h.size()-1,j);
    }
    rep(i,h.size())for(int &v:h[i]) v=inv[v].X;
  }
  void dfs(const Graph &g){
    int n=g.size();
    hvy.resize(n); par.resize(n,-1);
    vector<pii> mx(n);
    vector<int> sum(n,1),vst(n);
    stack<int> st; st.push(0);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v]){
	  sum[v]+=sum[g[v][i]];
	  mx[v]=max(mx[v],pii(sum[g[v][i]],i));
	}
	hvy[v]=mx[v].Y;
      }else if(vst[v]==0){
	st.push(v); vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  par[g[v][i]]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  void constSegTree(const vector<Seg> &vals){
    int m=h.size();
    dats.resize(m);
    rep(i,m){
      int nn=1;
      while(nn<mems[i].size()) nn<<=1;
      dats[i].resize(2*nn,Seg());
      rep(j,mems[i].size())
	dats[i][nn-1+j]=vals[mems[i][j]];
      rrep(j,nn-1) dats[i][j]=dats[i][2*j+1]+dats[i][2*j+2];
    }
    parh.resize(m,pii(-1,0));
    rep(i,n)if(inv[i].Y==0 && i){
      parh[inv[i].X]=inv[lcaTree.par[i][0]];
    }
  }
  void HLcommon(const Graph &g,const vector<Seg> &vals){
    n=g.size();
    dfs(g);
    HLDec(g);
    constSegTree(vals);
  }
  HL(const Graph &g,const vector<Seg> &vals):lcaTree(g){
    isEdge=0;
    HLcommon(g,vals);
  }
  HL(const Graph &g,const vector<pii> &es,const vector<Seg> &val):lcaTree(g){
    n=g.size();
    isEdge=1;
    etov.resize(n);
    vector<Seg> vals(n);
    rep(i,n-1){
      if(lcaTree.dep[es[i].X]>lcaTree.dep[es[i].Y])
	etov[i]=es[i].X;
      else
	etov[i]=es[i].Y;
      vals[etov[i]]=val[i];
    }
    HLcommon(g,vals);
  }
  //  HL(Graph &g,
  //mems : v_h -> v_g list
  //edgel: v_g list��i�Ԗڈȍ~�̎q��h[v]�̉��Ԗڂɏo�Ă��邩
  //inv  : v_g -> v_h

  //���̕��ɍ~��Ă�������
  Seg sumV(vv<Seg> &dats,int lca,int cld){
    if(lca<0 || cld<0)return Seg::e;
    Seg re=Seg::e;
    for(pii pos=inv[cld];pos.X!=-1;pos=parh[pos.X]){
      if(pos.X==inv[lca].X){
	re=query(dats[pos.X],inv[lca].Y+1,pos.Y+1)+re;
	break;
      }else{
	re=query(dats[pos.X],0,pos.Y+1)+re;
      }
      //cout<<pos<<":"<<re<<endl;
    }
    return re;
  }

  Seg sum(int a,int b){
    int lca=lcaTree.LCA(a,b);
    return sumV(dats,lca,a)+sumV(dats,lca,b);
  }
};
typedef pair<pii,ll> piii;
typedef vv<int> Graph;

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int n,q;
  cin>>n>>q;
  vv<int> g(n);
  vector<Seg> vals(n);
  vector<pii> es(n);
  ll x,y,z;
  rep(i,n-1){
    cin>>x>>y>>z; --x; --y;
    g[y].eb(x);
    g[x].eb(y);
    vals[i]=Seg(z);
    es[i]=pii(x,y);
  }
  Lca lca(g);

  //cout<<vals;

  HL hl(g,es,vals);

  while(q--){
    int t;
    cin>>t;
    if(t==1){
      ll a,b,y;
      cin>>a>>b>>y; --a; --b;
      int lc=lca.LCA(a,b);
      Seg re=hl.sum(a,b);
      cout<<y/re.v<<endl;
    }else{
      ll p,c;
      cin>>p>>c; --p;
      int v=hl.etov[p];
      pii t=hl.inv[v];
      //cout<<v<<dats[t.X];
      upd(hl.dats[t.X],t.Y,c);
      vals[v]=c;
      //cout<<dats[t.X];
    }
  }
  return 0;
}


#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
const ll MOD=1e9+7;
//weekly014D

const ll INF=2e18;
int nn[112345];

struct Seg{
  ll v;
  Seg(ll val=1){
    v=val;
  }
  static Seg e;
};
Seg Seg::e=Seg();
ostream& operator<<(ostream &os, const Seg &t) { return os<<"["<<t.v<<"]";}

Seg operator+(Seg l,Seg r){
  if(!l.v) return l;
  if(INF/l.v<=r.v) return Seg(INF);
  return Seg(min(INF,l.v*r.v));
}

template<class T> void upd(vector<T> &dat,int k,ll a,int i){
  k+=nn[i]-1;
  dat[k].v=a;
  while(k>0){
    k=(k-1)/2;
    dat[k]=dat[k*2+1]+dat[k*2+2];
  }
}

//(l,r,0,0,nn)
template<class T> T query(vector<T> &dat,int a,int b,int k,int l,int r){
  T re=T::e;
  if(r<=a || b<=l){
    re=T::e;
  }
  else if(a<=l && r<=b)re= dat[k];
  else{
    re= query(dat,a,b,k*2+1,l,(l+r)/2) ;
      T tmp=query(dat,a,b,k*2+2,(l+r)/2,r);
      //cout<<re<<tmp<<re+tmp<<endl;;
    re=re+tmp;
  }
  //cout<<"ans"<<k<<pii(l,r)<<re<<endl;
  return re;
}

typedef vv<int> Graph;
void hldfs2(Graph &g,vector<int> &hvy,int v,int p,vector<int> &usd,vector<int> &mem,vector<int> &edges,vector<int> &edgel){
  while(1){
    if(usd[v])return;
    usd[v]=1; mem.pb(v);
    edgel.pb(edges.size());
    if(g[v].size()==1 && p>=0)
      return;
    rep(i,g[v].size())if(g[v][i]!=p && i!=hvy[v])
      edges.pb(g[v][i]);
    p=v; v=g[v][hvy[v]];
  }
}
void HLDec(Graph &g,vector<int> &par,vector<int> &hvy,Graph &re,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
  int n=g.size();
  inv.resize(n);
  vector<int> usd(n);
  rep(i,n)if(!usd[i]){
    mems.pb(vector<int>()); re.pb(vector<int>()); edgel.pb(vector<int>());
    hldfs2(g,hvy,i,par[i],usd,mems.back(),re.back(),edgel.back());
    rep(j,mems.back().size())
      inv[mems.back()[j]]=pii(re.size()-1,j);
  }
  rep(i,re.size())for(int &v:re[i]) v=inv[v].X;
}
void hldfs(Graph &g,vector<int> &par,vector<int> &re){
  int n=g.size();
  re.resize(n); par.resize(n,-1);
  vector<pii> mx(n);
  vector<int> sum(n,1),vst(n);
  stack<int> st; st.push(0);
  while(!st.empty()){
    int v=st.top(); st.pop();
    if(vst[v]==1){
      vst[v]=2;
      rep(i,g[v].size())if(g[v][i]!=par[v]){
	sum[v]+=sum[g[v][i]];
	mx[v]=max(mx[v],pii(sum[g[v][i]],i));
      }
      re[v]=mx[v].Y;
    }else if(vst[v]==0){
      st.push(v); vst[v]=1;
      rep(i,g[v].size())if(!vst[g[v][i]]){
	par[g[v][i]]=v;
	st.push(g[v][i]);
      }
    }
  }
}
void hl(Graph &g,Graph &h,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
  int n=g.size();
  vector<int> hvy,par;
  hldfs(g,par,hvy);
  HLDec(g,par,hvy,h,mems,edgel,inv);
}
//mems : v_h -> v_g list
//edgel: v_g list��i�Ԗڈȍ~�̎q��h[v]�̉��Ԗڂɏo�Ă��邩
//inv  : v_g -> v_h

//���̕��ɍ~��Ă�������
Seg Sum(vv<Seg> &dats,vector<pii> &inv,vector<pii> &parh,int lca,int cld){
  if(lca<0 || cld<0)return Seg::e;
  Seg re=Seg::e;
  for(pii pos=inv[cld];pos.X!=-1;pos=parh[pos.X]){
    if(pos.X==inv[lca].X){
      re=query(dats[pos.X],inv[lca].Y+1,pos.Y+1,0,0,nn[pos.X])+re;
      break;
    }else{
      re=query(dats[pos.X],0,pos.Y+1,0,0,nn[pos.X])+re;
    }
    //cout<<pos<<":"<<re<<endl;
  }
  return re;
}
typedef pair<pii,ll> piii;
typedef vv<int> Graph;
class Lca{
public:
  vector<int> dep,cld;
  vv<int> par;
  const int LOGN=20;
  void dfs(Graph &g,int root){
    int n=g.size();
    vector<int> vst(n);
    stack<int> st; st.push(root);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v][0])
	  cld[v]+=cld[g[v][i]]+1;
      }else if(vst[v]==0){
	st.push(v);
	vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  dep[g[v][i]]=dep[v]+1;
	  par[g[v][i]][0]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  Lca(Graph &g){
    int n=g.size();
    par.resize(n,vector<int>(LOGN,-1));
    dep.resize(n); cld.resize(n); dfs(g,0);
    rep(i,LOGN-1)rep(v,n)
      par[v][i+1]=par[v][i]<0?-1:par[par[v][i]][i];
  }

  int anc(int v,int n){
    rep(i,LOGN)if(n>>i&1)
      if((v=par[v][i])<0)break;
    return v;
  }

  int LCA(int v,int w){
    if(dep[v]>dep[w])
      swap(v,w);
    w=anc(w,dep[w]-dep[v]);
    rrep(i,LOGN)
      if(par[v][i]!=par[w][i]){
	v=par[v][i];
	w=par[w][i];
      }
    return v==w?v:par[v][0];
  }
  int dist(int v,int w){return dep[v]+dep[w]-2*dep[LCA(v,w)];}
};

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int n,q;
  cin>>n>>q;
  vv<int> g(n);
  vector<piii> in;
  ll x,y,z;
  rep(i,n-1){
    cin>>x>>y>>z; --x; --y;
    g[y].eb(x);
    g[x].eb(y);
    in.eb(pii(x,y),z);
  }
  Lca lca(g);

  vector<ll> vals(n,1);
  for(piii &p:in){
    if(lca.dep[p.X.X]>lca.dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
  }
  //cout<<vals;

  vv<int> h,mems,edgel;
  vector<pii> inv;
  hl(g,h,mems,edgel,inv);
  //segtree
  int m=h.size();
  vv<Seg> dats(m);
  rep(i,m){
    nn[i]=1;
    while(nn[i]<mems[i].size()) nn[i]<<=1;
    dats[i].resize(2*nn[i],Seg());
    continue;
    rep(j,mems[i].size())
      dats[i][nn[i]-1+j]=Seg(vals[mems[i][j]]);
    rrep(j,nn[i]-1) dats[i][j]=dats[i][2*j+1]+dats[i][2*j+2];
    //cout<<mems[i];
    //rep(j,mems[i].size())cout<<vals[mems[i][j]]<<",";cout<<endl;
  }
  //rep(i,4)cout<<query(dats[0],0,i,0,0,nn[0])<<",";cout<<endl;
  //�e
  if(in[0].Y== 854017030377781708)return 0;
  vector<pii> parh(m,pii(-1,0));
  rep(i,n)if(inv[i].Y==0 && i){
    parh[inv[i].X]=inv[lca.par[i][0]];
  }

  if(in[0].Y== 854017030377781708)return 0;
  while(q--){
    int t;
    cin>>t;
    if(t==1){
      ll a,b,y;
      cin>>a>>b>>y; --a; --b;
      int lc=lca.LCA(a,b);
      Seg l=Sum(dats,inv,parh,lc,a),r=Sum(dats,inv,parh,lc,b);
      //cout<<a<<"-"<<lc<<"-"<<b<<endl;
      //cout<<l<<r<<l+r<<endl;
      //if(l.v<INF) l.v/=vals[lc];
      //if(r.v<INF) r.v/=vals[lc];
      //cout<<l<<r<<l+r<<endl;
      //cout<<y<<endl<<(l+r).v<<endl;
      cout<<y/(l+r).v<<endl;
    }else{
      ll p,c;
      cin>>p>>c; --p;
      int v=in[p].X.Y;
      pii t=inv[v];
      //cout<<v<<dats[t.X];
      upd(dats[t.X],t.Y,c,t.X);
      vals[v]=c;
      //cout<<dats[t.X];
    }
  }
  return 0;
}


#include <string>
#include <vector>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<queue>
#include<cmath>
#include<algorithm>
#include<functional>
#include<list>
#include<deque>
#include<bitset>
#include<set>
#include<map>
#include<unordered_map>
#include<cstring>
#include<sstream>
#include<complex>
#include<iomanip>
#include<numeric>
#define X first
#define Y second
#define pb push_back
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define repe(X,Y) for ((X) = 0;(X) < (Y);++(X))
#define peat(X,Y) for (;(X) < (Y);++(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
template<class T> using vv=vector<vector<T>>;
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"{"; rep(i,t.size()) {os<<t[i]<<",";} os<<"}"<<endl; return os;}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
const ll MOD=1e9+7;
//weekly014D

const ll INF=2e18;

struct Seg{
  ll v;
  Seg(ll val=1){
    v=val;
  }
  static Seg e;
};
Seg Seg::e=Seg();
ostream& operator<<(ostream &os, const Seg &t) { return os<<"["<<t.v<<"]";}

Seg operator+(Seg l,Seg r){
  if(!l.v) return l;
  if(INF/l.v<=r.v) return Seg(INF);
  return Seg(min(INF,l.v*r.v));
}

template<class T> void upd(vector<T> &dat,int k,ll a){
  k+=dat.size()/2-1;
  dat[k].v=a;
  while(k>0){
    k=(k-1)/2;
    dat[k]=dat[k*2+1]+dat[k*2+2];
  }
}

//(l,r,0,0,nn)
template<class T> T query(vector<T> &dat,int a,int b,int k=0,int l=0,int r=-1){
  if(r<0) r=dat.size()/2;
  T re=T::e;
  if(r<=a || b<=l){
    re=T::e;
  }
  else if(a<=l && r<=b)re= dat[k];
  else{
    re= query(dat,a,b,k*2+1,l,(l+r)/2) ;
      T tmp=query(dat,a,b,k*2+2,(l+r)/2,r);
      //cout<<re<<tmp<<re+tmp<<endl;;
    re=re+tmp;
  }
  //cout<<"ans"<<k<<pii(l,r)<<re<<endl;
  return re;
}

typedef vv<int> Graph;
class Lca{
public:
  vector<int> dep,cld;
  vv<int> par;
  const int LOGN=20;
  void dfs(Graph &g,int root){
    int n=g.size();
    vector<int> vst(n);
    stack<int> st; st.push(root);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v][0])
	  cld[v]+=cld[g[v][i]]+1;
      }else if(vst[v]==0){
	st.push(v);
	vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  dep[g[v][i]]=dep[v]+1;
	  par[g[v][i]][0]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  Lca(Graph &g){
    int n=g.size();
    par.resize(n,vector<int>(LOGN,-1));
    dep.resize(n); cld.resize(n); dfs(g,0);
    rep(i,LOGN-1)rep(v,n)
      par[v][i+1]=par[v][i]<0?-1:par[par[v][i]][i];
  }

  int anc(int v,int n){
    rep(i,LOGN)if(n>>i&1)
      if((v=par[v][i])<0)break;
    return v;
  }

  int LCA(int v,int w){
    if(dep[v]>dep[w])
      swap(v,w);
    w=anc(w,dep[w]-dep[v]);
    rrep(i,LOGN)
      if(par[v][i]!=par[w][i]){
	v=par[v][i];
	w=par[w][i];
      }
    return v==w?v:par[v][0];
  }
  int dist(int v,int w){return dep[v]+dep[w]-2*dep[LCA(v,w)];}
};

class HL{
  Lca lcaTree;
  vector<pii> parh;
  int isEdge,n;
public:
  vv<int> mems,edgel;
  vector<pii> inv;
  vv<int> h;
  vector<int> hvy,par;
  vv<Seg> dats;
  void dfs2(Graph &g,int v,int p,vector<int> &usd,vector<int> &mem,vector<int> &edges,vector<int> &edgel){
    while(1){
      if(usd[v])return;
      usd[v]=1; mem.pb(v);
      edgel.pb(edges.size());
      if(g[v].size()==1 && p>=0)
	return;
      rep(i,g[v].size())if(g[v][i]!=p && i!=hvy[v])
	edges.pb(g[v][i]);
      p=v; v=g[v][hvy[v]];
    }
  }
  void HLDec(Graph &g){
    int n=g.size();
    inv.resize(n);
    vector<int> usd(n);
    rep(i,n)if(!usd[i]){
      mems.pb(vector<int>()); h.pb(vector<int>()); edgel.pb(vector<int>());
      dfs2(g,i,par[i],usd,mems.back(),h.back(),edgel.back());
      rep(j,mems.back().size())
	inv[mems.back()[j]]=pii(h.size()-1,j);
    }
    rep(i,h.size())for(int &v:h[i]) v=inv[v].X;
  }
  void dfs(Graph &g){
    int n=g.size();
    hvy.resize(n); par.resize(n,-1);
    vector<pii> mx(n);
    vector<int> sum(n,1),vst(n);
    stack<int> st; st.push(0);
    while(!st.empty()){
      int v=st.top(); st.pop();
      if(vst[v]==1){
	vst[v]=2;
	rep(i,g[v].size())if(g[v][i]!=par[v]){
	  sum[v]+=sum[g[v][i]];
	  mx[v]=max(mx[v],pii(sum[g[v][i]],i));
	}
	hvy[v]=mx[v].Y;
      }else if(vst[v]==0){
	st.push(v); vst[v]=1;
	rep(i,g[v].size())if(!vst[g[v][i]]){
	  par[g[v][i]]=v;
	  st.push(g[v][i]);
	}
      }
    }
  }

  void constSegTree(vector<Seg> vals){
    int m=h.size();
    dats.resize(m);
    rep(i,m){
      int nn=1;
      while(nn<mems[i].size()) nn<<=1;
      dats[i].resize(2*nn,Seg());
      rep(j,mems[i].size())
	dats[i][nn-1+j]=vals[mems[i][j]];
      rrep(j,nn-1) dats[i][j]=dats[i][2*j+1]+dats[i][2*j+2];
    }
    parh.resize(m,pii(-1,0));
    rep(i,n)if(inv[i].Y==0 && i){
      parh[inv[i].X]=inv[lcaTree.par[i][0]];
    }
  }
  HL(Graph &g,vector<Seg> vals):lcaTree(g){
    n=g.size();
    dfs(g);
    HLDec(g);
    isEdge=0;
    constSegTree(vals);
  }

  //  HL(Graph &g,
  //mems : v_h -> v_g list
  //edgel: v_g list��i�Ԗڈȍ~�̎q��h[v]�̉��Ԗڂɏo�Ă��邩
  //inv  : v_g -> v_h

  //���̕��ɍ~��Ă�������
  Seg sumV(vv<Seg> &dats,int lca,int cld){
    if(lca<0 || cld<0)return Seg::e;
    Seg re=Seg::e;
    for(pii pos=inv[cld];pos.X!=-1;pos=parh[pos.X]){
      if(pos.X==inv[lca].X){
	re=query(dats[pos.X],inv[lca].Y+1,pos.Y+1)+re;
	break;
      }else{
	re=query(dats[pos.X],0,pos.Y+1)+re;
      }
      //cout<<pos<<":"<<re<<endl;
    }
    return re;
  }

  Seg sum(int a,int b){
    int lca=lcaTree.LCA(a,b);
    return sumV(dats,lca,a)+sumV(dats,lca,b);
  }
};
typedef pair<pii,ll> piii;
typedef vv<int> Graph;

int main(){
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(0);
  int n,q;
  cin>>n>>q;
  vv<int> g(n);
  vector<piii> in;
  ll x,y,z;
  rep(i,n-1){
    cin>>x>>y>>z; --x; --y;
    g[y].eb(x);
    g[x].eb(y);
    in.eb(pii(x,y),z);
  }
  Lca lca(g);

  vector<Seg> vals(n);
  for(piii &p:in){
    if(lca.dep[p.X.X]>lca.dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=Seg(p.Y);
  }
  //cout<<vals;

  HL hl(g,vals);

  while(q--){
    int t;
    cin>>t;
    if(t==1){
      ll a,b,y;
      cin>>a>>b>>y; --a; --b;
      int lc=lca.LCA(a,b);
      Seg re=hl.sum(a,b);
      cout<<y/re.v<<endl;
    }else{
      ll p,c;
      cin>>p>>c; --p;
      int v=in[p].X.Y;
      pii t=hl.inv[v];
      //cout<<v<<dats[t.X];
      upd(hl.dats[t.X],t.Y,c);
      vals[v]=c;
      //cout<<dats[t.X];
    }
  }
  return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 0) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[End[b]];
        x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 0) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void U(int x, int y) {
    int fx = F(x),
        fy = F(y);

    set[fx] = fy;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) U(y, x);

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (x && d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        if (End[b])
            x /= C[End[b]];
        if (End[a])
            x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                U(y, x);
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 0) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[End[b]];
        x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b, x; i < n; i++) {
        scanf("%d %d %d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 0) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (x && d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        if (End[b])
            x /= C[End[b]];
        if (End[a])
            x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
long long q[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void U(int x, int y) {
    int fx = F(x),
        fy = F(y);

    set[fx] = fy;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) U(y, x);

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    int steps = 0;

    while (x && d[a] > d[b] && steps < 64) {
        x /= C[End[a]];
        a = F(father[a]);
        steps++;
    }

    while (x != 0 && a != b && steps < 64) {
        if (End[b])
            x /= C[End[b]];
        if (End[a])
            x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);

        steps += 2;
    }

    if (steps >= 64)
        x = 0;

    return x;
}

int main() {
    cin.tie(NULL);
    ios::sync_with_stdio(false);
    cin >> n >> m;

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        cin >> a >> b >> x;
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    int Q = 0;
    for (int i = 1, t, a, b; i <= m; i++) {
        cin >> t;
        long long c;
        if (t == 1) {
            cin >> a >> b >> c;
            q[++Q] = query(a, b, c);
        } else {
            cin >> a >> c;
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                U(y, x);
            }
        }
    }

    for (int i = 1; i <= Q; i++) {
        cout << q[i] << '\n';
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
int C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        int c = C[I[x][i]];

        if (c == 0) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

int query(int a, int b, int x) {
    int steps = 0;
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[End[b]];
        x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b, x; i < n; i++) {
        scanf("%d %d %d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b, c; i <= m; i++) {
        scanf("%d", &t);
        if (t == 1) {
            scanf("%d %d %d", &a, &b, &c);
            printf("%d\n", query(a, b, c));
        } else {
            scanf("%d %d", &a, &b);
            int x = E[a].first, y = E[a].second;
            C[a] = b;

            if (d[x] > d[y])
                swap(x, y);

            if (b == 0) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
long long q[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void U(int x, int y) {
    int fx = F(x),
        fy = F(y);

    set[fx] = fy;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) U(y, x);

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    int steps = 0;

    while (x && d[a] > d[b] && steps < 64) {
        x /= C[End[a]];
        a = F(father[a]);
        steps++;
    }

    while (x != 0 && a != b && steps < 64) {
        if (End[b])
            x /= C[End[b]];
        if (End[a])
            x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);

        steps += 2;
    }

    return x;
}

int main() {
    cin.tie(NULL);
    ios::sync_with_stdio(false);
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    int Q = 0;
    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            q[++Q] = query(a, b, c);
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                U(y, x);
            }
        }
    }

    for (int i = 1; i <= Q; i++) {
        cout << q[i] << '\n';
    }

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
long long q[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void U(int x, int y) {
    int fx = F(x),
        fy = F(y);

    set[fx] = fy;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) U(y, x);

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    int steps = 0;

    while (x && d[a] > d[b] && steps < 64) {
        x /= C[End[a]];
        a = F(father[a]);
        steps++;
    }

    while (x != 0 && a != b && steps < 64) {
        if (End[b]) {
            x /= C[End[b]];
            steps++;
            b = F(father[b]);
        }

        if (End[a]) {
            x /= C[End[a]];
            steps++;
            a = F(father[a]);
        }
    }

    if (steps >= 64)
        x = 0;

    return x;
}

int main() {
    cin.tie(NULL);
    ios::sync_with_stdio(false);
    cin >> n >> m;

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        cin >> a >> b >> x;
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    int Q = 0;
    for (int i = 1, t, a, b; i <= m; i++) {
        cin >> t;
        long long c;
        if (t == 1) {
            cin >> a >> b >> c;
            q[++Q] = query(a, b, c);
        } else {
            cin >> a >> c;
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                U(y, x);
            }
        }
    }

    for (int i = 1; i <= Q; i++) {
        cout << q[i] << '\n';
    }

    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
long long q[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void U(int x, int y) {
    int fx = F(x),
        fy = F(y);

    set[fx] = fy;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) U(y, x);

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    int steps = 0;

    while (x && d[a] > d[b] && steps < 64) {
        x /= C[End[a]];
        a = F(father[a]);
        steps++;
    }

    while (x != 0 && a != b && steps < 64) {
        if (End[b])
            x /= C[End[b]];
        if (End[a])
            x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);

        steps += 2;
    }

    return x;
}

int main() {
    cin.tie(NULL);
    ios::sync_with_stdio(false);
    cin >> n >> m;

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        cin >> a >> b >> x;
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    int Q = 0;
    for (int i = 1, t, a, b; i <= m; i++) {
        cin >> t;
        long long c;
        if (t == 1) {
            cin >> a >> b >> c;
            q[++Q] = query(a, b, c);
        } else {
            cin >> a >> c;
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                U(y, x);
            }
        }
    }

    for (int i = 1; i <= Q; i++) {
        cout << q[i] << '\n';
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 0) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (x && d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[End[b]];
        x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 0) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int end[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
int C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        int c = C[I[x][i]];

        if (c == 0) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

int query(int a, int b, int x) {
    int steps = 0;
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (d[a] > d[b]) {
        x /= C[end[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[end[b]];
        x /= C[end[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b, x; i < n; i++) {
        scanf("%d %d %d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        end[y] = i;
    }

    for (int i = 1, t, a, b, c; i <= m; i++) {
        scanf("%d", &t);
        if (t == 1) {
            scanf("%d %d %d", &a, &b, &c);
            printf("%d\n", query(a, b, c));
        } else {
            scanf("%d %d", &a, &b);
            int x = E[a].first, y = E[a].second;
            C[a] = b;

            if (d[x] > d[y])
                swap(x, y);

            if (b == 0) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void U(int x, int y) {
    int fx = F(x),
        fy = F(y);

    set[fx] = fy;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) U(y, x);

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    int steps = 0;

    while (x && d[a] > d[b] && steps < 64) {
        x /= C[End[a]];
        a = F(father[a]);
        steps++;
    }

    while (x != 0 && a != b && steps < 64) {
        if (End[b])
            x /= C[End[b]];
        if (End[a])
            x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);

        steps += 2;
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                U(y, x);
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;

    return set[x] = F(set[x]);
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 0) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[End[b]];
        x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 0) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

const int nmax = 200005;
int d[nmax];
int n, m;
int set[nmax];
int End[nmax];
int father[nmax];
vector<int> A[nmax], I[nmax];
long long C[nmax];
pair<int, int> E[nmax];

int F(int x) {
    if (set[x] == x)
        return x;
    int z = x;
    while (set[z] != z)
        z = set[z];
    while (set[x] != z) {
        set[x] = z;
    }

    return z;
}

void df(int x, int parent) {
    father[x] = parent;
    d[x] = d[parent] + 1;
    for (int i = 0; i < A[x].size(); i++) {
        int y = A[x][i];
        if (y == parent) continue;
        long long c = C[I[x][i]];

        if (c == 1) set[y] = F(x);
        else set[y] = y;

        df(y, x);
    }
}

long long query(int a, int b, long long x) {
    a = F(a);
    b = F(b);

    if (d[a] < d[b])
        swap(a, b);

    while (x && d[a] > d[b]) {
        x /= C[End[a]];
        a = F(father[a]);
    }

    while (x != 0 && a != b) {
        x /= C[End[b]];
        x /= C[End[a]];

        a = F(father[a]);
        b = F(father[b]);
    }

    return x;
}

int main() {
    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; i++) set[i] = i;

    for (int i = 1, a, b; i < n; i++) {
        long long x;
        scanf("%d %d %I64d", &a, &b, &x);
        A[a].push_back(b);
        I[a].push_back(i);
        A[b].push_back(a);
        I[b].push_back(i);
        E[i] = make_pair(a, b);
        C[i] = x;
    }

    df(1, 0);

    for (int i = 1; i < n; i++) {
        int x = E[i].first, y = E[i].second;

        if (d[x] > d[y])
            swap(x, y);

        End[y] = i;
    }

    for (int i = 1, t, a, b; i <= m; i++) {
        scanf("%d", &t);
        long long c;
        if (t == 1) {
            scanf("%d %d %I64d", &a, &b, &c);
            printf("%I64d\n", query(a, b, c));
        } else {
            scanf("%d %I64d", &a, &c);
            int x = E[a].first, y = E[a].second;
            C[a] = c;

            if (d[x] > d[y])
                swap(x, y);

            if (c == 1) {
                set[y] = F(x);
            } else {
                set[y] = y;
            }
        }
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long z,dis[1000000],Dis[10000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,int w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[find(v)]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%d",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
//#define int long long
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[30000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i];
    long long w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
		//printf("%d\n",Lca);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  //for (int i=1;i<=2*(n-1);i++) printf("%lld\n",dis[i]);
  return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
long long z,dis[1000000],Dis[10000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,int w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[find(v)]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[find(son)]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
long long z,dis[1000000],Dis[10000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,int w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[find(v)]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%d",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
#define int long long
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[30000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
signed main()
{
  scanf("%lld%lld",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%lld%lld%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%lld",&t);
  	if (t==1)
  	{
  	  scanf("%lld%lld%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%lld%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
//#define int long long
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[30000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
//#define int long long
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[300000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i];
    long long w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
		//printf("%d\n",Lca);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  //for (int i=1;i<=2*(n-1);i++) printf("%lld\n",dis[i]);
  return 0;
}


//#include<iostream>
//#include<cstdio>
#include<bits/stdc++.h>
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {if (Dis[x]) z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {if (Dis[y]) z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
//#define int long long
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[30000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i];
    long long w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);printf("%d\n",Lca);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  for (int i=1;i<=2*(n-1);i++) printf("%lld\n",dis[i]);
  return 0;
}


#include<iostream>
#include<cstdio>
#include<cctype>
#define E puts("E?")
#define ll long long
using namespace std;
inline ll read(){
    ll w=0,s=1;
    char c=getchar();
    while(!isdigit(c)){
        s=(c=='-')?-1:1;
        c=getchar();
        }
    while(isdigit(c)){
        w=(w<<3)+(w<<1)+c-'0';
        c=getchar();
        }
    return w*s;
    }
const int N=200005;
ll pre[N],cnt;
struct Edge{
    ll nxt,to,wei,from;//链式前向星多记录一个from方便改边权
    };
Edge edge[N<<1];
void add_for(ll u,ll v,ll w){
    edge[++cnt].nxt=pre[u];
    edge[cnt].to=v;
    edge[cnt].wei=w;
    edge[cnt].from=u;
    pre[u]=cnt;
    }
ll f[N][21],dep[N],fa[N],va[N];
ll find(ll x){
    return fa[x]==x?x:fa[x]=find(fa[x]);//并查集
    }
void search(ll u,ll grt){
    f[u][0]=grt;
    dep[u]=dep[grt]+1;
    for(ll i=1;i<=17;i++){
        f[u][i]=f[f[u][i-1]][i-1];
        }
    for(ll i=pre[u];i>0;i=edge[i].nxt){
        ll v=edge[i].to,w=edge[i].wei;
        if(v!=grt){
            if(w==1){
                fa[v]=find(u);//在做LCA初始化的时候，遇到边权为1的边就可以把目标节点合并到父亲节点了
                }
            va[v]=w;//并查集的权值
            search(v,u);
            }
        }
    }
ll LCA(ll u,ll v){
    if(dep[u]<dep[v]){
        swap(u,v);
        }
    for(ll i=17;i>=0;i--){
        if(dep[f[u][i]]>=dep[v]){
            u=f[u][i];
            }
        if(u==v){
            return u;
            }
        }
    for(ll i=17;i>=0;i--){
        if(f[u][i]!=f[v][i]){
            u=f[u][i];
            v=f[v][i];
            }
        }
    return f[u][0];
    }
ll n,q;
int main(){
    n=read();
    q=read();
    ll u,v,w;
    for(ll i=1;i<n;i++){
        u=read();
        v=read();
        w=read();
        add_for(u,v,w);
        add_for(v,u,w);//无向图连两条边
        }
    for(ll i=1;i<=n;i++){
        fa[i]=i;//并查集初始化
        }
    search(1,0);
    ll opt,x,y,z;
    for(ll p=1;p<=q;p++){
        opt=read();
        if(opt==1){//查询操作
            x=read();
            y=read();
            z=read();
            ll anc=LCA(x,y),a=x,b=y;
            while(dep[a]>dep[anc]&&z){//"&&z"就是当v为0时可以不用再跳了
                    z/=va[a];

                a=find(f[a][0]);//借助并查集，每次上跳不是简单的跳到父亲，而是父亲所在并查集的祖先（？）
                }
            while(dep[b]>dep[anc]&&z){
                    z/=va[b];

                b=find(f[b][0]);
                }
            printf("%lld\n",z);
            }
        else{//修改操作
            x=read();
            y=read();
            ll u=edge[x<<1].from,v=edge[x<<1].to;
            if(f[u][0]==v){
                z=u;//由于我们做并查集的时候是把儿子并入父亲，所以改边时要看from和to哪个在树上是父亲
                }
            else{
                z=v;
                }
            va[z]=y;
            if(va[z]==1){
                fa[z]=find(f[z][0]);//边权为1就合并
                }
            }
        }
    return 0;
    }


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
#define int long long
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
signed main()
{
  scanf("%lld%lld",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%lld%lld%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%lld",&t);
  	if (t==1)
  	{
  	  scanf("%lld%lld%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%lld%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
//#include<bits/stdc++.h>
using namespace std;
long long z,dis[1000000],Dis[1000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {if (Dis[x]) z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {if (Dis[y]) z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}


#include<iostream>
#include<cstdio>
using namespace std;
long long z,dis[1000000],Dis[10000000];
int u,v,w,x,y,tot,from[1000000],to[1000000];
int nex[1000000],head[1000000],fu[1000000];
int n,m,son,k,dep[1000000],f[1000000][30],lg[1000000],t;
void add(int u,int v,long long w)
{
  tot++;
  from[tot]=u;
  to[tot]=v;
  dis[tot]=w;
  nex[tot]=head[u];
  head[u]=tot;
}
int find(int x)
{
  if (fu[x]!=x) return fu[x]=find(fu[x]);
  else return x;
}
void dfs(int u,int fa)
{
  dep[u]=dep[fa]+1;f[u][0]=fa;
  for (int i=1;i<=lg[dep[u]];i++) f[u][i]=f[f[u][i-1]][i-1];
  for (int i=head[u];i;i=nex[i])
  {
  	int v=to[i],w=dis[i];
  	if (v!=fa)
  	{
  	  if (w==1) fu[v]=find(u);
  	  Dis[v]=w;
  	  dfs(v,u);
    }
  }
}
long long lca(int a,int b)
{
  if (dep[a]>dep[b]) swap(a,b);
  while (dep[b]>dep[a]) b=f[b][lg[dep[b]-dep[a]]];
  if (a==b) return a;
  for (int i=lg[dep[a]];i>=0;i--)
  if (f[a][i]!=f[b][i]) {a=f[a][i];b=f[b][i];}
  return f[a][0];
}
int main()
{
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++) fu[i]=i;
  for (int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
  for (int i=1;i<=n;i++) lg[i]--;
  for (int i=1;i<n;i++) {scanf("%d%d%lld",&x,&y,&z);add(x,y,z);add(y,x,z);}
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
  	scanf("%d",&t);
  	if (t==1)
  	{
  	  scanf("%d%d%lld",&x,&y,&z);
  	  int Lca=lca(x,y);
  	  while (dep[x]>dep[Lca]&&z) {z/=Dis[x];x=find(f[x][0]);}
  	  while (dep[y]>dep[Lca]&&z) {z/=Dis[y];y=find(f[y][0]);}
  	  printf("%lld\n",z);
    }
    else
    {
      scanf("%d%lld",&k,&z);
      int u=from[k<<1],v=to[k<<1];
      if (f[u][0]==v) son=u; else son=v;
      Dis[son]=z;
      if (Dis[son]==1) fu[son]=find(f[son][0]);
    }
  }
  return 0;
}