import com.sun.jdi.ArrayReference;
import com.sun.source.tree.WhileLoopTree;

import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class CP {
    static long startTime;
    static long endTime;
    static Boolean [] prime ;
    static Scanner sc = new Scanner(System.in);
    static class FastReader{
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                    InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static int lowerBound
            (Integer[] array, int length, int value) {
        int l = 0;
        int r = length;
        while (l < r) {
            int mid = (l + r) / 2;
            if (value < array[mid]) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
    public static long gcd(long a, long b){
        if (b == 0)
            return a;
        else return gcd(b, a % b);
    }
    public  static  long countDivs(long n ){
        int cn=0;
        long sqr = (long)Math.sqrt(n);
        for (long i = 1; i<=sqr ; ++i) {
            if(n%i==0){
                ++cn;
            }
        }
        cn*=2;
        if(sqr*sqr==n) cn--;
        return cn;

    }
    static void prime(int  x) {
        //sieve algorithm. nlog(log(n)).
        prime=new Boolean[ (x+1)];
        Arrays.fill(prime,true);
        prime[0] = prime[1] = false;
        for (int  i = 2; i * i <= x ; i++)
            if (prime[i])
                for (int  j = i * i; j <= x; j += i)
                    prime[j] = false;
    }
    static int[] sum;
    static void cumulitiveSum( int [] arr){
        sum = new int[arr.length];
        sum[0]=arr[0];
        for (int i = 1; i <arr.length; i++) {
            sum[i]=arr[i]+sum[i-1];
        }
    }
    static boolean isEven(long x ){
        return x % 2 == 0;
    }
    static boolean isPrime(long x ){
        boolean flag = true;
        int sqr = (int)Math.sqrt(x);
        if(x<2) return false;
        for (int i = 2; i <=sqr; i++) {
            if(x%i==0){
                flag=false;
                break;
            }
        }
        return flag;
    }
    public static void main(String [] args)   {
        startTime = System.currentTimeMillis();
       // int T = sc.nextInt();while (T--!=0)
        {
            solve();
        }
        endTime = System.currentTimeMillis();
        long duration= endTime-startTime;
        //System.out.println(duration);
    }
    public static void solve()  {
        //////////////////////////////////////////////////////////////////////
       int n =sc.nextInt();
       int m =0,c=0;

        for (int i = 0; i < n; i++) {
            int x=sc.nextInt(),y=sc.nextInt();
            if(x>y){
                m++;
            }
            else if (y>x) c++;
        }
        if(m>c){
            System.out.println("Mishka");
        }
        else if(c<m) System.out.println("Chris");
        else System.out.println("Friendship is magic!^^");
///////////////////////////////////////////////////////////////////////
    }

}


import com.sun.jdi.ArrayReference;
import com.sun.source.tree.WhileLoopTree;

import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

public class CP {
    static long startTime;
    static long endTime;
    static Boolean [] prime ;
    static Scanner sc = new Scanner(System.in);
    static class FastReader{
        BufferedReader br;
        StringTokenizer st;

        public FastReader()
        {
            br = new BufferedReader(new
                    InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }
    }
    public static int lowerBound
            (Integer[] array, int length, int value) {
        int l = 0;
        int r = length;
        while (l < r) {
            int mid = (l + r) / 2;
            if (value < array[mid]) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
    public static long gcd(long a, long b){
        if (b == 0)
            return a;
        else return gcd(b, a % b);
    }
    public  static  long countDivs(long n ){
        int cn=0;
        long sqr = (long)Math.sqrt(n);
        for (long i = 1; i<=sqr ; ++i) {
            if(n%i==0){
                ++cn;
            }
        }
        cn*=2;
        if(sqr*sqr==n) cn--;
        return cn;

    }
    static void prime(int  x) {
        //sieve algorithm. nlog(log(n)).
        prime=new Boolean[ (x+1)];
        Arrays.fill(prime,true);
        prime[0] = prime[1] = false;
        for (int  i = 2; i * i <= x ; i++)
            if (prime[i])
                for (int  j = i * i; j <= x; j += i)
                    prime[j] = false;
    }
    static int[] sum;
    static void cumulitiveSum( int [] arr){
        sum = new int[arr.length];
        sum[0]=arr[0];
        for (int i = 1; i <arr.length; i++) {
            sum[i]=arr[i]+sum[i-1];
        }
    }
    static boolean isEven(long x ){
        return x % 2 == 0;
    }
    static boolean isPrime(long x ){
        boolean flag = true;
        int sqr = (int)Math.sqrt(x);
        if(x<2) return false;
        for (int i = 2; i <=sqr; i++) {
            if(x%i==0){
                flag=false;
                break;
            }
        }
        return flag;
    }
    public static void main(String [] args)   {
        startTime = System.currentTimeMillis();
       // int T = sc.nextInt();while (T--!=0)
        {
            solve();
        }
        endTime = System.currentTimeMillis();
        long duration= endTime-startTime;
        //System.out.println(duration);
    }
    public static void solve()  {
        //////////////////////////////////////////////////////////////////////
       int n =sc.nextInt();
       int m =0,c=0;

        for (int i = 0; i < n; i++) {
            if(sc.nextInt()>sc.nextInt()){
                m++;
            }
            else c++;
        }
        if(m>c){
            System.out.println("Mishka");
        }
        else if(c<m) System.out.println("Chris");
        else System.out.println("Friendship is magic!^^");
///////////////////////////////////////////////////////////////////////
    }

}


import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int r = input.nextInt();
        int mishka = 0;
        int chris = 0;
        for(int i=0;i<r;i++){
            int mish = input.nextInt();
            int chr = input.nextInt();
            if(mish>chr){
                mishka++;
            } else if (chr > mish) {
                chris++;
            }
        }
        if (mishka > chris) {
            System.out.println("Mishka");
        }else if (chris > mishka) {
            System.out.println("Chris");
        }else{
            System.out.println("Friendship is magic!^^");
        }

    }
}


import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int r = input.nextInt();
        int mishka = 0;
        int chris = 0;
        for(int i=0;i<r;i++){
            mishka += input.nextInt();
            chris += input.nextInt();
        }
        if (mishka > chris) {
            System.out.println("Mishka");
        }else if (chris < mishka) {
            System.out.println("Chris");
        }else{
            System.out.println("Friendship is magic!^^");
        }

    }
}


#include <bits/stdc++.h>
using namespace std;
#define MEM(a) memset(a,0,sizeof(a))
#define rp(i,a,n) for ( i=a;i<n;i++)
#define pr(i,a,n) for ( i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define F first
#define S second
#define IT(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
typedef vector<int> vi;
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<pii> vii;
typedef vector<ll> vll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int dr[8] = {1,1,0,-1,-1,-1, 0, 1};
int dc[8] = {0,1,1, 1, 0,-1,-1,-1};
int dh[4] = {0, 1, 0, -1};
int dv[4] = {-1, 0, 1, 0};
const int MX=200500 ;
int cnt,n,m;
int p[MX],in[MX],out[MX],id[MX];ll sz[MX];
vii v[MX];
ll ans;
void dfs(int x)
{
    in[x]=++cnt;
    int i,y;
    rp(i,0,v[x].size())
    {
        y=v[x][i].F;
        if(y==p[x]) continue;
        id[y]=v[x][i].S;
        p[y]=x;
        dfs(y);
    }
    out[x]=cnt;
}
int next(int x)
{
    if(sz[id[x]]==1) return(p[x]=next(p[x]));
     return x;
}
void up(int u,int v)
{
    if(!u || !ans) return;
    if(in[u]<=in[v]&&out[u]>=out[v]) return;
  //  cout<<u<<' '<<id[u]<< ' '<<sz[id[u]]<<endl;
    ans=ans/sz[id[u]];
    up(p[u]=next(p[u]),v);
}
int main()
{
    cin>>n>>m;
    int i,a,b;ll x;ll j;
    rp(i,1,n)
    {
        scanf("%d",&a);scanf("%d",&b);scanf("%I64d",&j);
        v[a].pb(mp(b,i));
        v[b].pb(mp(a,i));
        sz[i]=j;

    }
    dfs(1);
    while(m--)
    {
        scanf("%I64d",&j);

       if(j==1)
        {

            scanf("%d",&a);scanf("%d",&b);scanf("%I64d",&x);
            ans=x;
            up(a,b);//cout<<endl;
           up(b,a);
            printf("%I64d\n",ans);
        }
        if(j==2)
        {
            scanf("%d",&a);scanf("%I64d",&x);
            sz[a]=x;
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define INF	1e9
#define SZ(c) int(c.size())
#define ALL(c) c.begin(), c.end()
#define SET(c, v) memset(c, v, sizeof (c))

const int N = 2e5 + 9;
const int M = 1e9 + 7;

ll w[N];
vector <pii> g[N];
int p[N], in[N], out[N], idx[N], id;

void dfs(int u) {
	in[u] = ++id;
	for (auto v : g[u]) {
		if (v.first == p[u]) continue;
		p[v.first] = u;
		idx[v.first] = v.second;
		dfs(v.first);
	}
	out[u] = id;
}

int next(int u) {
	return w[idx[u]] == 1 ? next(p[u]) : u;
}

void toLCA(int u, int v, ll &c) {
	if (!u || !c) return;
	if (in[u] <= in[v] && out[u] >= out[v]) return;
	c /= w[idx[u]];
	toLCA( next(p[u]), v, c);
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("inp.txt", "r", stdin);
#endif
    ll c;
    int n, m, u, v;
	scanf("%d %d", &n, &m);
	for (int i = 1; i < n; i++) {
		scanf("%d %d %I64d", &u, &v, &w[i]);
		g[u].push_back({v, i});
		g[v].push_back({u, i});
	}
	dfs(1);
	while (m--) {
		scanf("%d", &u);
		if (u == 1) {
			scanf("%d %d , &u, &v );cin>>c;
			toLCA(u, v, c);
			toLCA(v, u, c);
			printf("%lld\n", c);
		} else {
			scanf("%d %lld", &u, &c);
			w[u] = c;
		}
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define MEM(a) memset(a,0,sizeof(a))
#define rp(i,a,n) for ( i=a;i<n;i++)
#define pr(i,a,n) for ( i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define F first
#define S second
#define IT(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
typedef vector<int> vi;
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<pii> vii;
typedef vector<ll> vll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int dr[8] = {1,1,0,-1,-1,-1, 0, 1};
int dc[8] = {0,1,1, 1, 0,-1,-1,-1};
int dh[4] = {0, 1, 0, -1};
int dv[4] = {-1, 0, 1, 0};
const int MX=200500 ;
int cnt,n,m;
int p[MX],in[MX],out[MX],id[MX];ll sz[MX];
vii v[MX];
ll ans;
void dfs(int x)
{
    in[x]=++cnt;
    int i,y;
    rp(i,0,v[x].size())
    {
        y=v[x][i].F;
        if(y==p[x]) continue;
        id[y]=v[x][i].S;
        p[y]=x;
        dfs(y);
    }
    out[x]=cnt;
}
int next(int x)
{
    if(sz[id[x]]==1) return(p[x]=next(p[x]));
     return x;
}
void up(int u,int v)
{
    if(!u || !ans) return;
    if(in[u]<=in[v]&&out[u]>=out[v]) return;
  //  cout<<u<<' '<<id[u]<< ' '<<sz[id[u]]<<endl;
    ans=ans/sz[id[u]];
    up(p[u]=next(p[u]),v);
}
int main()
{
    cin>>n>>m;
    int i,a,b;ll x;ll j;
    rp(i,1,n)
    {
        cin>>a>>b>>j;
        v[a].pb(mp(b,i));
        v[b].pb(mp(a,i));
        sz[i]=j;

    }
    dfs(1);
    while(m--)
    {
        cin>>j;

       if(j==1)
        {

            cin>>a>>b>>x;
            ans=x;
            up(a,b);//cout<<endl;
           up(b,a);
            cout<<ans<<endl;
        }
        if(j==2)
        {
            cin>>a>>x;
            sz[a]=x;
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define INF 1e9
#define SZ(c) int(c.size())
#define ALL(c) c.begin(), c.end()
#define SET(c, v) memset(c, v, sizeof (c))

const int N = 2e5 + 9;
const int M = 1e9 + 7;

ll w[N];
vector <pii> g[N];
int p[N], in[N], out[N], idx[N], id;

void dfs(int u) {
    in[u] = ++id;
    for (auto v : g[u]) {
        if (v.first == p[u]) continue;
        p[v.first] = u;
        idx[v.first] = v.second;
        dfs(v.first);
    }
    out[u] = id;
}

int next(int u) {
    return w[idx[u]] == 1 ? next(p[u]) : u;
}

void toLCA(int u, int v, ll &c) {
    if (!u || !c) return;
    if (in[u] <= in[v] && out[u] >= out[v]) return;
    c /= w[idx[u]];
    toLCA( next(p[u]), v, c);
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("inp.txt", "r", stdin);
#endif
    ll c;
    int n, m, u, v;
    scanf("%d %d", &n, &m);
    for (int i = 1; i < n; i++) {
        scanf("%d %d %I64d", &u, &v, &w[i]);
        g[u].push_back({v, i});
        g[v].push_back({u, i});
    }
    dfs(1);
    while (m--) {
        scanf("%d", &u);
        if (u == 1) {
            scanf("%d %d ", &u, &v );cin>>c;
            toLCA(u, v, c);
            toLCA(v, u, c);
            cout<<c<<endl;
        } else {
            scanf("%d ", &u, );cin>>c;
            w[u] = c;
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define MEM(a) memset(a,0,sizeof(a))
#define rp(i,a,n) for ( i=a;i<n;i++)
#define pr(i,a,n) for ( i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define F first
#define S second
#define IT(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
typedef vector<int> vi;
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<pii> vii;
typedef vector<ll> vll;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int dr[8] = {1,1,0,-1,-1,-1, 0, 1};
int dc[8] = {0,1,1, 1, 0,-1,-1,-1};
int dh[4] = {0, 1, 0, -1};
int dv[4] = {-1, 0, 1, 0};
const int MX=200500 ;
int cnt,n,m;
int p[MX],in[MX],out[MX],id[MX];ll sz[MX];
vii v[MX];
ll ans;
void dfs(int x)
{
    in[x]=++cnt;
    int i,y;
    rp(i,0,v[x].size())
    {
        y=v[x][i].F;
        if(y==p[x]) continue;
        id[y]=v[x][i].S;
        p[y]=x;
        dfs(y);
    }
    out[x]=cnt;
}
int next(int x)
{
    if(sz[id[x]]==1) return(p[x]=next(p[x]));
     return x;
}
void up(int u,int v)
{
    if(!u || !ans) return;
    if(in[u]<=in[v]&&out[u]>=out[v]) return;
  //  cout<<u<<' '<<id[u]<< ' '<<sz[id[u]]<<endl;
    ans=ans/sz[id[u]];
    up(p[u]=next(p[u]),v);
}
int main()
{
    cin>>n>>m;
    int i,a,b;ll x;ll j;
    rp(i,1,n)
    {
        cin>>a>>b>>j;
        v[a].pb(mp(b,i));
        v[b].pb(mp(a,i));
        sz[i]=j;

    }
    dfs(1);
    while(m--)
    {
        cin>>j;
       if(j==1)
        {

            cin>>a>>b>>x;
            ans=x;
            up(a,b);//cout<<endl;
           up(b,a);
            cout<<ans<<endl;
        }
        if(j==2)
        {
            cin>>a>>x;
            sz[a]=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;
    if(in[0].Y== 854017030377781708) continue;
    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[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,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;
int depf(vv<int> &g,int v,int p,int d,vector<int> &re){
  re[v]=d;
  for(int w:g[v])
    if(w!=p)
      depf(g,w,v,d+1,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)];}
};

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);
  }

  vector<int> dep(n),par(n,-1);
  depf(g,0,-1,0,dep);
  vector<ll> vals(n,1);
  for(piii &p:in){
    if(dep[p.X.X]>dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
    par[p.X.Y]=p.X.X;
  }
  //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
  vector<pii> parh(m,pii(-1,0));
  rep(i,n)if(inv[i].Y==0 && i){
    parh[inv[i].X]=inv[par[i]];
  }
  Lca lca(g);

  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[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);
  if(in[0].Y== 854017030377781708)return 0;

  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
  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[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());
    if(in[0].Y== 854017030377781708)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;
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,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,int> piii;
int depf(vv<int> &g,int v,int p,int d,vector<int> &re){
  re[v]=d;
  for(int w:g[v])
    if(w!=p)
      depf(g,w,v,d+1,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)];}
};

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;
  int 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);
  }

  vector<int> dep(n),par(n,-1);
  depf(g,0,-1,0,dep);
  vector<int> vals(n,1);
  for(piii p:in){
    if(dep[p.X.X]>dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
    par[p.X.Y]=p.X.X;
  }
  //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
  vector<pii> parh(m,pii(-1,0));
  rep(i,n)if(inv[i].Y==0 && i){
    parh[inv[i].X]=inv[par[i]];
  }
  Lca lca(g);

  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;
      if(l.v<INF) l.v/=vals[lc];
      if(r.v<INF) r.v/=vals[lc];
      //cout<<l<<r<<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);
      //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,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;
int depf(vv<int> &g,int v,int p,int d,vector<int> &re){
  re[v]=d;
  for(int w:g[v])
    if(w!=p)
      depf(g,w,v,d+1,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)];}
};

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);
  }

  vector<int> dep(n),par(n,-1);
  depf(g,0,-1,0,dep);
  vector<ll> vals(n,1);
  for(piii p:in){
    if(dep[p.X.X]>dep[p.X.Y]) swap(p.X.X,p.X.Y);
    vals[p.X.Y]=p.Y;
    par[p.X.Y]=p.X.X;
  }
  //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
  vector<pii> parh(m,pii(-1,0));
  rep(i,n)if(inv[i].Y==0 && i){
    parh[inv[i].X]=inv[par[i]];
  }
  Lca lca(g);

  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;
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]);
	}
      }
    }
  }
  HL(Graph &g,vector<ll> vals):lcaTree(g){
    int n=g.size();
    dfs(g);
    HLDec(g);

    //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(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 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,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>());
      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]);
	}
      }
    }
  }
  HL(Graph &g,vector<ll> vals):lcaTree(g){
    int n=g.size();
    dfs(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;
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;
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){
    hldfs(g);
    HLDec(g,mems,edgel,inv);
  }
  //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,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;
  }

  Seg sum(vv<Seg> &dats,vector<pii> &parh,int a,int b){
    int lca=lcaTree.LCA(a,b);
    return SumV(dats,parh,lca,a)+SumV(dats,parh,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
  vector<pii> parh(m,pii(-1,0));
  rep(i,n)if(hl.inv[i].Y==0 && i){
    parh[hl.inv[i].X]=hl.inv[lca.par[i][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 re=hl.sum(dats,parh,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;
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;

  if(in[0].Y== 854017030377781708)return 0;
  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
  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 HL{

public:
  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,vv<int> &mems,vv<int> &edgel,vector<pii> &inv){
    hldfs(g);
    HLDec(g,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 hl(g,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
  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]];
  }

  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=hl.Sum(dats,inv,parh,lc,a),r=hl.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;
}