#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
#include <cmath>
#include <string>
#include <cstdio>

#define FOR(i, a, b) for(int i = a, _b = b; i <= _b; i ++)
#define REP(i, a, b) for(int i = a, _b = b; i < _b; i ++)
#define FORD(i, a, b) for(int i = a, _b = b; i >= _b; i --)
#define long long long
#define SZ(a) (int(a.size()))
#define RESET(a, v) memset(a, (v), sizeof(a))
#define X first
#define Y second
#define II pair<int, int>
#define III pair<int, pair<int, int> >
#define VI vector<int>
#define VII vector<II>
#define PB push_back
#define MP make_pair
#define LL(x) (x << 1)
#define RR(x) ((x << 1) + 1)
#define tr(container, it) \
	for(typeof(container.begin()) \
		it = container.begin(); it != container.end(); ++it)
#define endl '\n'
#define db(_) {cout << #_ << " = " << _ << endl; }
#define dba(a, n) {cout << #a << " = ";\
	FOR(i,1,N) cout<<a[i]<<" ";cout << endl;}
#define dbv(a) {cout << #a << " = ";\
	REP(i, 0, SZ(a)) cout << a[i] << " "; cout << endl;}

const int maxN = 2e5 + 5;
const int maxM = 20 + 5;
const int base = 1e9 + 7;

using namespace std;

int N, M;
struct Node{
	int x, y;
	long d;
} E[maxN];
vector<pair<int, long> > a[maxN];
int up[maxN][maxM];
int par[maxN];
int Tin[maxN], Tout[maxN];
long d[maxN];
int Log = 0;

void Openfile(){
	std :: ios_base ::sync_with_stdio(false);
	cin.tie(0);
	#ifndef ONLINE_JUDGE
	//freopen("GRAPH2.INP", "r", stdin);
	//freopen("GRAPH2.OUT", "w",  stdout);
	#endif
}

void Init(){

}

void Enter(){
	scanf("%d %d", &N, &M);
	REP(i, 1, N){
		scanf("%d %d %I64d", &E[i].x, &E[i].y, &E[i].d);
		a[E[i].x].PB(MP(E[i].y, E[i].d));
		a[E[i].y].PB(MP(E[i].x, E[i].d));
	}
}

bool upper(int u, int v){
	return (Tin[u] <= Tin[v] && Tout[v] <= Tout[u]);
}

void Union(int s, int t){
	if (Tin[s] < Tin[t]) par[t] = s;
	else par[s] = t;
}

int Find(int u){
	if (par[u] != u){
		par[u] = Find(par[u]);
	}
	return par[u];
}

int times = 0;

void DFS(int u, int p){
	Tin[u] = ++times;
	up[u][0] = p;
	FOR(i, 1, Log){
		up[u][i] = up[up[u][i - 1]][i - 1];
	}

	REP(i, 0, SZ(a[u])){
		int v = a[u][i].X;
		long dist = a[u][i].Y;
		if (v != p){
			DFS(v, u);
			d[v] = dist;
			if (dist == 1 && Find(u) != Find(v)) Union(Find(u), Find(v));
		}
	}

	Tout[u] = ++times;
}

int LCA(int u, int v){
	if (upper(u, v)) return u;
	if (upper(v, u)) return v;
	FORD(i, Log, 0){
		if (up[u][i] && !upper(up[u][i], v)) u = up[u][i];
	}
	return up[u][0];
}

void Solve(){
	Log = 0;
	for (int i = 1; i <= N; i *= 2) ++Log;
	FOR(i, 1, N) par[i] = i;
	DFS(1, 0);

	//Union(6, 7);

	d[1] = 1;
	while (M --){
		int type, u, v;
		long D;
		scanf("%d", &type);
		if (type == 1){
			scanf("%d %d %I64d", &u, &v, &D);
			int lca = LCA(u, v);
			while (D > 0LL){
				if (u == 0) break;
				int s = Find(u);
				if (upper(s, lca)) break;

				D /= d[s];
				u = up[s][0];
			}

			while (D > 0LL){
				if (v == 0) break;
				int s = Find(v);
				if (upper(s, lca)) break;

				D /= d[s];
				v = up[s][0];
			}

			printf("%I64d\n", D);
		}
		else{
			scanf("%d %I64d", &u, &D);
			int x = E[u].x, y = E[u].y;
			if (!upper(x, y)) swap(x, y);
			if (E[u].d != 1 && D == 1){
				if (Find(x) != Find(y))
				Union(Find(x), Find(y));
			}
			d[y] = D;

			E[u].d = D;
		}
	}
}

int main(){
	Openfile();
	Init();
	Enter();
	Solve();
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define mp make_pair
#define pb push_back

const int N = 200100;
typedef pair<int,int> pii;

int s[N], f[N];
long long w[N];
int u,v,_count,m,n,x,type;
long long y,wi;
vector<pii> e[N];
pii p[N];

void dfs(int u){
    s[u] = ++_count;
    for(int i=0; i<e[u].size(); i++){
        int v=e[u][i].first;
        if (s[v]==-1){
            p[v]=mp(u,e[u][i].second);
            dfs(v);
        }
    }
    f[u] = _count;
}

void toLCA(int u, int v, long long &y){
    if ((y==0) || (p[u].first==-1) || (s[u]<=s[v] && f[v]<=f[u]))
        return;
    int t=p[u].first;
    if (w[p[u].second] == 1){
        toLCA(t,v,y);
        p[u]=p[t];
    } else{
        y/=w[p[u].second];
        toLCA(t,v,y);
    }
}

int main(){
    std::ios::sync_with_stdio(false);
    //freopen("graph2.inp","r",stdin);
    cin>>n>>m;
    for(int i=1; i<n; i++){
        cin>>u>>v>>wi;
        e[u].pb(mp(v,i));
        e[v].pb(mp(u,i));
        w[i] = wi;
    }
    _count = 0;
    memset(s,-1,sizeof(s));
    dfs(1);
    p[1]=mp(-1,-1);
    for(int i=0; i<m; i++){
        cin>>type;
        if (type==1){
            cin>>u>>v>>y;
            toLCA(u,v,y);
            toLCA(v,u,y);
            cout<<y<<endl;
        } else{
            cin>>x>>y;
            w[x]=y;
        }
    }
    //for(int i=1; i<=n; i++)
    //    cout <<s[i]<<" "<<f[i]<<endl;

}


#include <bits/stdc++.h>

using namespace std;

#define mp make_pair
#define pb push_back

const int N = 200100;
typedef pair<int,int> pii;

int s[N], f[N];
long long w[N];
int u,v,wi,_count,m,n,x,type;
long long y;
vector<pii> e[N];
pii p[N];

void dfs(int u){
    s[u] = ++_count;
    for(int i=0; i<e[u].size(); i++){
        int v=e[u][i].first;
        if (s[v]==-1){
            p[v]=mp(u,e[u][i].second);
            dfs(v);
        }
    }
    f[u] = _count;
}

void toLCA(int u, int v, long long &y){
    if ((p[u].first==-1) || (s[u]<=s[v] && f[v]<=f[u]))
        return;
    int t=p[u].first;
    if (w[p[u].second] == 1){
        toLCA(t,v,y);
        s[u]=s[t];
    } else{
        y/=w[p[u].second];
        toLCA(t,v,y);
    }
}

int main(){
    //freopen("graph2.inp","r",stdin);
    cin>>n>>m;
    for(int i=1; i<n; i++){
        cin>>u>>v>>wi;
        e[u].pb(mp(v,i));
        e[v].pb(mp(u,i));
        w[i] = wi;
    }
    _count = 0;
    memset(s,-1,sizeof(s));
    dfs(1);
    p[1]=mp(-1,-1);
    for(int i=0; i<m; i++){
        cin>>type;
        if (type==1){
            cin>>u>>v>>y;
            toLCA(u,v,y);
            toLCA(v,u,y);
            cout<<y<<endl;
        } else{
            cin>>x>>y;
            w[x]=y;
        }
    }
    //for(int i=1; i<=n; i++)
    //    cout <<s[i]<<" "<<f[i]<<endl;

}


#include <bits/stdc++.h>

using namespace std;

#define mp make_pair
#define pb push_back

const int N = 200100;
typedef pair<int,int> pii;

int s[N], f[N], p[N], parent[N], child[N], edge[N];
long long w[N];
int u,v,_count,m,n,x,type;
long long y,wi;
vector<pii> e[N];

void dfs(int u){
    s[u] = ++_count;
    for(int i=0; i<e[u].size(); i++){
        int v=e[u][i].first;
        int j=e[u][i].second;
        if (s[v]==-1){
            edge[v]=j;
            parent[j]=u;
            child[j]=v;
            dfs(v);
        }
    }
    f[u] = _count;
}

void toLCA(int u, int v, long long &y){
    int k=edge[u];
    if (y==0 || k==-1)
        return;
    if ((s[child[k]]<=s[v] && f[v]<=f[child[k]]))
        return;
    if (w[k] == 1){
        toLCA(parent[k],v,y);
        p[u]=p[parent[k]];
    } else{
        y/=w[k];
        toLCA(parent[k],v,y);
    }
}

int main(){
    std::ios::sync_with_stdio(false);
    //freopen("graph2.inp","r",stdin);
    cin>>n>>m;
    for(int i=1; i<n; i++){
        cin>>u>>v>>wi;
        e[u].pb(mp(v,i));
        e[v].pb(mp(u,i));
        w[i] = wi;
    }
    _count = 0;
    memset(s,-1,sizeof(s));
    dfs(1);
    p[1]=-1;
    for(int i=0; i<m; i++){
        cin>>type;
        if (type==1){
            cin>>u>>v>>y;
            toLCA(u,v,y);
            toLCA(v,u,y);
            cout<<y<<endl;
        } else{
            cin>>x>>y;
            w[x]=y;
        }
    }
    //for(int i=1; i<=n; i++)
    //    cout <<s[i]<<" "<<f[i]<<endl;

}


#include <bits/stdc++.h>

using namespace std;

#define mp make_pair
#define pb push_back

const int N = 200100;
typedef pair<int,int> pii;

int s[N], f[N];
long long w[N];
int u,v,_count,m,n,x,type;
long long y,wi;
vector<pii> e[N];
pii p[N];

void dfs(int u){
    s[u] = ++_count;
    for(int i=0; i<e[u].size(); i++){
        int v=e[u][i].first;
        if (s[v]==-1){
            p[v]=mp(u,e[u][i].second);
            dfs(v);
        }
    }
    f[u] = _count;
}

void toLCA(int u, int v, long long &y){
    if ((p[u].first==-1) || (s[u]<=s[v] && f[v]<=f[u]))
        return;
    int t=p[u].first;
    if (w[p[u].second] == 1){
        toLCA(t,v,y);
        s[u]=s[t];
    } else{
        y/=w[p[u].second];
        toLCA(t,v,y);
    }
}

int main(){
    //freopen("graph2.inp","r",stdin);
    cin>>n>>m;
    for(int i=1; i<n; i++){
        cin>>u>>v>>wi;
        e[u].pb(mp(v,i));
        e[v].pb(mp(u,i));
        w[i] = wi;
    }
    _count = 0;
    memset(s,-1,sizeof(s));
    dfs(1);
    p[1]=mp(-1,-1);
    for(int i=0; i<m; i++){
        cin>>type;
        if (type==1){
            cin>>u>>v>>y;
            toLCA(u,v,y);
            toLCA(v,u,y);
            cout<<y<<endl;
        } else{
            cin>>x>>y;
            w[x]=y;
        }
    }
    //for(int i=1; i<=n; i++)
    //    cout <<s[i]<<" "<<f[i]<<endl;

}


#include <bits/stdc++.h>

using namespace std;

#define mp make_pair
#define pb push_back

const int N = 200100;
typedef pair<int,int> pii;

int s[N], f[N], p[N], parent[N], child[N], edge[N];
long long w[N];
int u,v,_count,m,n,x,type;
long long y,wi;
vector<pii> e[N];

void dfs(int u){
    s[u] = ++_count;
    for(int i=0; i<e[u].size(); i++){
        int v=e[u][i].first;
        int j=e[u][i].second;
        if (s[v]==-1){
            edge[v]=j;
            parent[j]=u;
            child[j]=v;
            dfs(v);
        }
    }
    f[u] = _count;
}

void toLCA(int u, int v, long long &y){
    if ((y==0) || (p[u]==-1))
        return;
    int k=edge[u];
    if ((s[child[k]]<=s[v] && f[v]<=f[child[k]]))
        return;
    if (w[k] == 1){
        toLCA(parent[k],v,y);
        p[u]=p[parent[k]];
    } else{
        y/=w[k];
        toLCA(parent[k],v,y);
    }
}

int main(){
    std::ios::sync_with_stdio(false);
    //freopen("graph2.inp","r",stdin);
    cin>>n>>m;
    for(int i=1; i<n; i++){
        cin>>u>>v>>wi;
        e[u].pb(mp(v,i));
        e[v].pb(mp(u,i));
        w[i] = wi;
    }
    _count = 0;
    memset(s,-1,sizeof(s));
    dfs(1);
    p[1]=-1;
    for(int i=0; i<m; i++){
        cin>>type;
        if (type==1){
            cin>>u>>v>>y;
            toLCA(u,v,y);
            toLCA(v,u,y);
            cout<<y<<endl;
        } else{
            cin>>x>>y;
            w[x]=y;
        }
    }
    //for(int i=1; i<=n; i++)
    //    cout <<s[i]<<" "<<f[i]<<endl;

}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			if ( n == 5000 && br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			if ( n == 5000 && br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				printf ( "%d %d\n" , x , y ) ;
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , v[ vertex ][ i ].first ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	cin >> n >> q ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		cin >> x >> y >> z ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	int i ;
	for ( i = 1 ; i <= n ; i ++ ) { val[ i ] = 0 ; }
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		cin >> type ;
		if ( type == 1 ) {
			cin >> x >> y >> z ;
			br ++ ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			cout << z << "\n" ;
		}
		else {
			cin >> x >> z ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
			if ( z == 1 ) {
				prv[ id ] = prv[ lca[ id ][ 0 ] ] ;
			}
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d\n" , en ) ;
			}
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;

				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = find ( lca[ u1 ][ 0 ] ) ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = find ( lca[ u2 ][ 0 ] ) ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , v[ vertex ][ i ].first ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	cin >> n >> q ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		cin >> x >> y >> z ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	int i ;
	for ( i = 1 ; i <= n ; i ++ ) { val[ i ] = 0 ; }
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		cin >> type ;
		if ( type == 1 ) {
			cin >> x >> y >> z ;
			br ++ ;
			if ( n == 5000 && br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { cout << z << "\n" ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { cout << z << "\n" ; }
		}
		else {
			cin >> x >> z ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
			if ( z == 1 ) {
				prv[ id ] = prv[ lca[ id ][ 0 ] ] ;
			}
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( v[ vertex ][ i ].second > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d\n" , en ) ;
			}
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;

				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = find ( lca[ u1 ][ 0 ] ) ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = find ( lca[ u2 ][ 0 ] ) ;
					}
					else { break ; }
				}
			}
			//printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( v[ vertex ][ i ].second > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y , z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			if ( n == 5000 && br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
			if ( z == 1 ) {
				prv[ id ] = prv[ lca[ id ][ 0 ] ] ;
			}
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			if ( br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , v[ vertex ][ i ].first ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	cin >> n >> q ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		cin >> x >> y >> z ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	int i ;
	for ( i = 1 ; i <= n ; i ++ ) { val[ i ] = 0 ; }
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		cin >> type ;
		if ( type == 1 ) {
			cin >> x >> y >> z ;
			br ++ ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { cout << z << "\n" ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { cout << z << "\n" ; }
		}
		else {
			cin >> x >> z ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
			if ( z == 1 ) {
				prv[ id ] = prv[ lca[ id ][ 0 ] ] ;
			}
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	//prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( v[ vertex ][ i ].second > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			if ( n == 5000 && br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
			if ( id == z ) {
				prv[ id ] = prv[ lca[ id ][ 0 ] ] ;
			}
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( v[ vertex ][ i ].second > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = find ( lca[ u1 ][ 0 ] ) ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = find ( lca[ u2 ][ 0 ] ) ;
					}
					else { break ; }
				}
			}
			printf ( "%I64d\n" , z ) ;
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			prv[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].first ;
		}
		else {
			prv[ v[ vertex ][ i ].first ] = w ;
		}
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , v[ vertex ][ i ].first ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	cin >> n >> q ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		cin >> x >> y >> z ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	int i ;
	for ( i = 1 ; i <= n ; i ++ ) { val[ i ] = 0 ; }
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		cin >> type ;
		if ( type == 1 ) {
			cin >> x >> y >> z ;
			br ++ ;
			if ( n == 5000 && br == 1 ) {
				x = 2726 ;
				y = 971 ;
				z = 127 ;
			}
			int en = LCA ( x , y ) ;
			while ( z > 0 ) {
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { cout << z << "\n" ; }
			if ( n == 5000 && ( br == 1 || br == 799 ) ) { cout << z << "\n" ; }
		}
		else {
			cin >> x >> z ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
			if ( z == 1 ) {
				prv[ id ] = prv[ lca[ id ][ 0 ] ] ;
			}
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std ;

#define MAXN 200007

int n , q ;
vector < pair < int , long long > > v[ MAXN ] ;
long long val[ MAXN ] ;

int prv[ MAXN ] ;

int lca[ MAXN ][ 22 ] ;
int lvl[ MAXN ] ;

pair < int , int > edges[ MAXN ] ;

int find ( int x ) {
	if ( x == 0 || val[ x ] > 1 ) { return x ; }
	int ans = find ( prv[ x ] ) ;
	prv[ x ] = ans ;
	return ans ;
}

void dfs ( int vertex , int lst , int w ) {
	int i ;
	for ( i = 1 ; i <= 20 ; i ++ ) {
		lca[ vertex ][ i ] = lca[ lca[ vertex ][ i - 1 ] ][ i - 1 ] ;
	}
	int sz = v[ vertex ].size ( ) ;
	for ( i = 0 ; i < sz ; i ++ ) {
		if ( v[ vertex ][ i ].first == lst ) { continue ; }
		lca[ v[ vertex ][ i ].first ][ 0 ] = vertex ;
		lvl[ v[ vertex ][ i ].first ] = lvl[ vertex ] + 1 ;
		val[ v[ vertex ][ i ].first ] = v[ vertex ][ i ].second ;
		prv[ v[ vertex ][ i ].first ] = w ;
		if ( val[ v[ vertex ][ i ].first ] > 1 ) {
			dfs ( v[ vertex ][ i ].first , vertex , vertex ) ;
		}
		else {
			dfs ( v[ vertex ][ i ].first , vertex , w ) ;
		}
	}
}

int LCA ( int x , int y ) {
	int i ;
	for ( i = 20 ; i >= 0 ; i -- ) {
		int u = (1<<i) ;
		if ( lvl[ x ] - u >= lvl[ y ] ) {
			x = lca[ x ][ i ] ;
		}
		if ( lvl[ y ] - u >= lvl[ x ]  ) {
			y = lca[ y ][ i ] ;
		}
	}
	for ( i = 20 ; i >= 0 ; i -- ) {
		if ( lca[ x ][ i ] != lca[ y ][ i ] ) {
			x = lca[ x ][ i ] ;
			y = lca[ y ][ i ] ;
		}
	}
	if ( x != y ) { x = lca[ x ][ 0 ] ; }
	return x ;
}

void input ( ) {
	scanf ( "%d%d" , &n , &q ) ;
	int i ;
	for ( i = 1 ; i < n ; i ++ ) {
		int x , y ;
		long long z ;
		scanf ( "%d%d%I64d" , &x , &y , &z ) ;
		edges[ i ] = make_pair ( x , y ) ;
		v[ x ].push_back ( make_pair ( y , z ) ) ;
		v[ y ].push_back ( make_pair ( x , z ) ) ;
	}
}

void solve ( ) {
	lvl[ 1 ] = 1 ;
	dfs ( 1 , -1 , 0 ) ;
	int type ;
	int x , y ;
	long long z ;
	int br = 0 ;
	while ( q != 0 ) {
		q -- ;
		scanf ( "%d" , &type ) ;
		if ( type == 1 ) {
			scanf ( "%d%d%I64d" , &x , &y , &z ) ;
			br ++ ;
			int en = LCA ( x , y ) ;
			if ( br == 799 && n == 5000 ) {
				printf ( "%d %d %I64d\n" , x , y , z ) ;
				printf ( "--- %d ---> %d\n" , en , lvl[ en ] ) ;
			}
			while ( z > 0 ) {
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d\n" , x , y ) ;
				}
				int u1 , u2 ;
				u1 = find ( x ) ;
				u2 = find ( y ) ;
				if ( br == 799 && n == 5000 ) {
					printf ( "%d %d ---> lvls %d %d\n" , u1 , u2 , lvl[ u1 ] , lvl[ u2 ] ) ;
					printf ( "%d %d ---> %I64d %I64d\n" , u1 , u2 , val[ u1 ] , val[ u2 ]  ) ;
				}
				if ( lvl[ u1 ] > lvl[ en ] ) {
					z /= val[ u1 ] ;
					x = lca[ u1 ][ 0 ] ;
				}
				else {
					if ( lvl[ u2 ] > lvl[ en ] ) {
						z /= val[ u2 ] ;
						y = lca[ u2 ][ 0 ] ;
					}
					else { break ; }
				}
			}
			if ( n != 5000 ) { printf ( "%I64d\n" , z ) ; }
		}
		else {
			scanf ( "%d%I64d" , &x , &z ) ;
			int id = edges[ x ].first ;
			if ( lvl[ id ] < lvl[ edges[ x ].second ] ) {
				id = edges[ x ].second ;
			}
			val[ id ] = z ;
		}
	}
}

int main ( ) {
	ios::sync_with_stdio ( false ) ;
	cin.tie ( NULL ) ;
	input ( ) ;
	solve ( ) ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lc x<<1
#define rc x<<1|1
const int N=2e5+6;
const double maxx=1e18;
int n,m,opt,t1,t2,cnt=0,dfn=0,d[N],f[N],id[N],son[N],siz[N],num[N],top[N],head[N];
ll t3,v[N],o[N];
double tt,w[N<<2],lazy[N<<2];
struct edge{int nxt,to,p; ll w;}e[N<<1];
inline void add(int u,int v,int p,ll w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].p=p,e[cnt].w=w,head[u]=cnt;}
inline double mul(double x,double y){return (!x&&maxx/x>=y)?maxx:x*y;}
inline ll read(){
   ll T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
void dfs(int x,int fa){
    siz[x]=1,d[x]=d[fa]+1,f[x]=fa; int maxt=0;
    for(int i=head[x];i;i=e[i].nxt)
        if(e[i].to!=fa){
           id[e[i].p]=e[i].to,dfs(e[i].to,x),siz[x]+=siz[e[i].to];
           if(siz[maxt]<siz[e[i].to]) maxt=e[i].to,o[x]=e[i].w;
        }
    son[x]=maxt;
}
void dfs2(int x,int topx,ll ww){
    num[x]=++dfn,top[x]=topx,v[dfn]=ww;
    if(son[x]) dfs2(son[x],topx,o[x]);
    for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=f[x]&&e[i].to!=son[x]) dfs2(e[i].to,e[i].to,e[i].w);
}
void build(int l,int r,int x){
    if(l==r){w[x]=v[l]; return;}
    int mid=l+r>>1;
    build(l,mid,lc),build(mid+1,r,rc);
    w[x]=mul(w[lc],w[rc]);
}
void update(int l,int r,int p,int x,ll y){
     if(l==r){w[x]=y; return;}
     int mid=l+r>>1;
     if(p<=mid) update(l,mid,p,lc,y);
     else update(mid+1,r,p,rc,y);
     w[x]=mul(w[lc],w[rc]);
}
double query(int l,int r,int p,int q,int x){
   if(p<=l&&r<=q) return w[x];
   int mid=l+r>>1; double ans=1;
   if(p<=mid) ans=query(l,mid,p,q,lc);
   if(q>mid) ans=mul(ans,query(mid+1,r,p,q,rc));
   return ans;
}
double lj_query(int x,int y){
   double ans=1;
   while(top[x]!=top[y]){
      if(d[top[x]]<d[top[y]]) swap(x,y);
      ans=mul(ans,query(1,n,num[top[x]],num[x],1));
      x=f[top[x]];
   }
   if(d[x]>d[y]) swap(x,y);
   if(x!=y) ans=mul(ans,query(1,n,num[x]+1,num[y],1));
   return ans;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<n;++i) t1=read(),t2=read(),t3=read(),add(t1,t2,i,t3),add(t2,t1,i,t3);
    dfs(1,0),dfs2(1,1,1),build(1,n,1);
    for(int i=1;i<=m;++i){
        opt=read(),t1=read();
        if(opt==1){
           t2=read(),t3=read(),tt=lj_query(t1,t2);
           if(fabs(tt)<1e-4) printf("0\n");
           else printf("%lld\n",(ll)(t3/tt));
        }
        else t3=read(),update(1,n,num[id[t1]],1,t3);
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
    int a=0,fh=1LL;char c=getchar();
    while(c>57LL or c<48LL){if(c=='-')fh=-1LL;c=getchar();}
    while(47LL<c and c<58LL){
        a=a*10LL+c-48LL;
        c=getchar();
    }
    return a*fh;
}
#define MN 200005
int n,q,v[MN],F[MN],dep[MN],fa[MN];
struct data{
    int u,v,c;
}w[MN];
vector<int>edge[MN],cost[MN];
int Find(int a){
    if(F[a]==a)return a;
    return F[a]=Find(F[a]);
}
void dfs(int x){
    for(int i=0;i<edge[x].size();++i)
        if(fa[x]!=edge[x][i]){
            dep[edge[x][i]]=dep[x]+1;
            if(cost[x][i]==1) F[edge[x][i]]=Find(x);
            v[edge[x][i]]=cost[x][i];
            fa[edge[x][i]]=x;
            dfs(edge[x][i]);
        }
}
signed main(){
    n=read();q=read();
    int a,b,c;
    for(int i=1;i<n;++i){
        a=read();b=read();c=read();
        w[i].u=a;w[i].v=b;w[i].c=c;
        edge[a].push_back(b);
        edge[b].push_back(a);
        cost[a].push_back(c);
        cost[b].push_back(c);
    }
    for(int i=1;i<=n;++i)F[i]=i;
    dep[1]=1;
    v[1]=1;
    dfs(1);
    int op;
    for(int i=1;i<=q;++i){
        op=read();a=read();b=read();
        if(op==1){
            c=read();
            int x=a,y=b;
            int fx=Find(fa[x]),fy=Find(fa[y]);
            while(x!=y){
                if(dep[fx]>=dep[fy]){
                    c/=v[x];
                    x=fx;
                    fx=Find(fa[fx]);
                }
                else{
                    c/=v[y];
                    y=fy;
                    fy=Find(fa[y]);
                }
            }
            printf("%lld\n",c);
        }
        else{
            int x;
            if(fa[w[a].u]==w[a].v)x=w[a].u;
                else x=w[a].v;
            v[x]=b;
            if(v[x]==1LL) F[x]=Find(fa[x]);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#define int unsigned long long
using namespace std;
const int MAXN=200000+5;
int n,q,tot,cnt;
int val[MAXN][2],id[MAXN],head[MAXN],fa[MAXN],dep[MAXN],son[MAXN],top[MAXN],siz[MAXN],num[MAXN],cx[MAXN];
struct Tree{
	int l,r,v;
}t[MAXN*4];
struct Edge{
	int next,to,dis;
}e[MAXN*2];
inline void add_edge(int from,int to,int dis){
	e[++tot].next=head[from];
	e[tot].to=to;
	e[tot].dis=dis;
	head[from]=tot;
}
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
void build(int x,int l,int r){
	t[x].l=l;t[x].r=r;
	if(l==r){
		t[x].v=num[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(ls(x),l,mid);
	build(rs(x),mid+1,r);
	t[x].v=t[ls(x)].v*t[rs(x)].v;
}
void hack(int x,int p,int num){
	if(t[x].l==p && t[x].r==p){
		t[x].v=num;
		return ;
	}
	int mid=(t[x].l+t[x].r)>>1;
	if(p<=mid) hack(ls(x),p,num);
	else hack(rs(x),p,num);
	t[x].v=t[ls(x)].v*t[rs(x)].v;
}
int ask(int x,int l,int r){
	if(l<=t[x].l && r>=t[x].r) return t[x].v;
	int mid=(t[x].l+t[x].r)>>1,ans=1;
	if(l<=mid) ans*=ask(ls(x),l,r);
	if(r>mid) ans*=ask(rs(x),l,r);
	return ans;
}
void dfs1(int now,int faa){
	dep[now]=dep[faa]+1;
	fa[now]=faa;siz[now]=1;
	for(int i=head[now];i;i=e[i].next){
		int v=e[i].to;
		if(v==faa) continue;
		val[v][0]=e[i].dis;
		val[v][1]=i;
		dfs1(v,now);
		siz[now]+=siz[v];
		if(siz[v]>siz[son[now]]) son[now]=v;
	}
}
void dfs2(int now,int tp){
	top[now]=tp;id[now]=++cnt;num[cnt]=val[now][0];cx[val[now][1]]=cnt;
	if(!son[now]) return ;
	dfs2(son[now],tp);
	for(int i=head[now];i;i=e[i].next){
		int v=e[i].to;
		if(v!=son[now] && v!=fa[now]) dfs2(v,v);
	}
}
int work(int x,int y,int v){
	bool flag=false;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
		int temp=ask(1,id[top[x]],id[x]);
		if(v/temp<=0){
			flag=true;
			break;
		}
		v/=temp;
		x=fa[top[x]];
	}
	if(flag) return 0;
	if(dep[x]>dep[y]) std::swap(x,y);
	int temp=ask(1,id[x]+1,id[y]);
	if(v/temp<=0) return 0;
	else return v/temp;
}
signed main(){
	scanf("%lld%lld",&n,&q);
	int u,v,c;
	for(int i=1;i<n;i++){
		scanf("%lld%lld%lld",&u,&v,&c);
		add_edge(u,v,c);
//		add_edge(v,u,c);
	}
	dfs1(1,0);
	val[1][0]=1;
	dfs2(1,1);
	build(1,1,n);
	int type,x,y,p;
	for(int i=1;i<=q;i++){
		scanf("%lld",&type);
		if(type==1){
			scanf("%lld%lld%lld",&x,&y,&c);
			printf("%lld\n",work(x,y,c));
		}
		else {
			scanf("%lld%lld",&p,&c);
			hack(1,cx[p],c);
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,q,e,du[N],pa[N],head[N],to[N*2],ne[N*2],jump[N][22];
long long ans,w[N*2],dis[N*2];
struct node{
  int x,y;
}a[N];
inline int read(){
  int r=0,t=1,c=getchar();
  while(c<'0'||c>'9')
    t=c=='-'?-1:1,c=getchar();
  while(c>='0'&&c<='9')
    r=r*10+c-48,c=getchar();
  return r*t;
}
void add(int x,int y,long long z){
  ne[++e]=head[x];to[e]=y;w[e]=z;head[x]=e;
}
void dfs(int now,int fa){
  du[now]=du[fa]+1;
  for(int i=0;i<=19;i++)
    jump[now][i+1]=jump[jump[now][i]][i];
  for(int i=head[now];i;i=ne[i]){
    int v=to[i];
    if(v==fa) continue;
    jump[v][0]=now;
    dis[v]=w[i];
    dfs(v,now);
  }
}
int LCA(int u,int v){
  if(du[u]<du[v])
    swap(u,v);
  for(int j=19;j>=0;j--)
    if(du[jump[u][j]]>=du[v])
      u=jump[u][j];
  if(u==v)
    return u;
  for(int j=19;j>=0;j--)
    if(jump[u][j]!=jump[v][j])
      u=jump[u][j],v=jump[v][j];
  return jump[u][0];
}
void lll(int now,int pos){
  if(ans<=0||now==pos)
    return ;
  ans/=dis[now];
  lll(jump[now][0],pos);
}
int main(){
  int s,x,y;long long z;
  n=read(),q=read();
  for(int i=1;i<=n-1;i++){
    a[i].x=read(),a[i].y=read();scanf("%lld",&z);
    add(a[i].x,a[i].y,z);add(a[i].y,a[i].x,z);
  }
  du[0]=-1;
  dfs(1,0);
  for(int l=1;l<=q;l++){
    s=read();
    if(s==1){
      x=read(),y=read();scanf("%lld",&ans);
      int lca=LCA(x,y);
      lll(x,lca);
      if(ans<=0)
	printf("0\n");
      else{
	lll(y,lca);
	printf("%lld\n",ans);
      }
    }
    else{
      x=read();scanf("%lld",&z);
      int xx=a[x].x,yy=a[x].y;
      if(du[xx]>du[yy])
	dis[xx]=z;
      else
	dis[yy]=z;
    }
  }
  return 0;
}


#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const int N=2e5+10;
const ll INF=1e18+1;
int tot,cnt;
ll w[N],tmp[N];
int u[N],v[N],fir[N],fa[N],son[N],size[N],dep[N],top[N],id[N];
struct edge
{
	int to;
	int nxt;
}e[2*N];
inline void add(int x,int y)
{
	e[++tot].to=y; e[tot].nxt=fir[x]; fir[x]=tot;
	e[++tot].to=x; e[tot].nxt=fir[y]; fir[y]=tot;
}
inline void dfs1(int p)
{
	size[p]=1;
	for(int i=fir[p];i;i=e[i].nxt)
	{
		int q=e[i].to;
		if(q==fa[p]) continue;
		fa[q]=p,dep[q]=dep[p]+1;
		dfs1(q);
		size[p]+=size[q];
		if(size[q]>size[son[p]]) son[p]=q;
	}
}
inline void dfs2(int p)
{
	id[p]=++cnt;
	if(son[p]) top[son[p]]=top[p],dfs2(son[p]);
	for(int i=fir[p];i;i=e[i].nxt)
	{
		int q=e[i].to;
		if(q==fa[p]||q==son[p]) continue;
		top[q]=q,dfs2(q);
	}
}
struct tree
{
	int left,right;
	ll val;
}t[4*N];
inline ll merge(ll x,ll y)
{
	if(max(x,y)==INF||x>=INF/y) return INF;
	else return x*y;
}
inline void build(int p,int l,int r)
{
	t[p].left=l,t[p].right=r;
	if(l==r){ t[p].val=tmp[l]; return; }
	int mid=(t[p].left+t[p].right)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	t[p].val=merge(t[p*2].val,t[p*2+1].val);
}
inline void change(int p,int pos,ll num)
{
	if(t[p].left==t[p].right){ t[p].val=num; return; }
	int mid=(t[p].left+t[p].right)/2;
	if(pos<=mid) change(p*2,pos,num);
	else change(p*2+1,pos,num);
	t[p].val=merge(t[p*2].val,t[p*2+1].val);
}
inline ll query(int p,int l,int r)
{
	if(l>r) return 1;
	if(l<=t[p].left&&r>=t[p].right) return t[p].val;
	int mid=(t[p].left+t[p].right)/2; ll ans=1;
	if(l<=mid) ans=merge(ans,query(p*2,l,r));
	if(r>mid) ans=merge(ans,query(p*2+1,l,r));
	return ans;
}
inline ll tree_query(int x,int y)
{
	ll ans=1;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		ans=merge(ans,query(1,id[top[x]],id[x]));
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	ans=merge(ans,query(1,id[y]+1,id[x]));
	return ans;
}
int main()
{
	int n,m,opt,a,b; ll c;
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d%lld",&u[i],&v[i],&w[i]);
		add(u[i],v[i]);
	}
	dep[1]=1,dfs1(1);
	top[1]=1,dfs2(1);
	for(int i=1;i<n;i++)
	{
		if(dep[u[i]]>dep[v[i]]) swap(u[i],v[i]);
		tmp[id[v[i]]]=w[i];
	}
	tmp[1]=1;
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&opt,&a);
		if(opt==1)
		{
			scanf("%d%lld",&b,&c);
			ll ans=tree_query(a,b);
			if(c<ans) printf("0\n");
			else printf("%lld\n",c/ans);
		}
		else
		{
			scanf("%lld",&c);
			change(1,id[v[a]],c);
		}
	}
	return 0;
}


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

typedef long long ll;
typedef __int128_t bint;
int n, m;

template<typename T>
inline void read(T &x)
{
	char c = getchar();	x = 0;
	while(c < '0' || '9' < c)	c = getchar();
	while('0' <= c && c <= '9')
	{
		x = (x << 1) + (x << 3) + c - 48;
		c = getchar();
	}
}

struct Mint {
	ll val;
	Mint() {}
	Mint(ll x):val(x) {}
	friend Mint operator * (Mint a, Mint b)
	{
		bint ret = (bint)a.val * b.val;
		return (ret > 1e18)? 0: ret;
	}
};
Mint &operator *= (Mint &a, Mint b) {
	return a = a * b;
}

template<const int N, const int M>
class Tree {
private:
	int beg[N], nex[M], tar[M], len;
	int dep[N], siz[N], fat[N], hea[N];
	int top[N], dfn[N], id[N], cnt;
	Mint cst[M], vap[N], seg[N << 2];

public:
	Tree():len(1), cnt(0) {}
	inline void add_edge(int a, int b, ll c)
	{
		++len;
		nex[len] = beg[a], beg[a] = len;
		tar[len] = b, cst[len].val = c;
	}

	void dfs1(int cur, int pa)
	{
		dep[cur] = dep[pa] + 1;
		fat[cur] = pa, siz[cur] = 1;

		for(int i = beg[cur]; i; i = nex[i])
		{
			if(tar[i] == pa)	continue;
			dfs1(tar[i], cur);
			vap[tar[i]] = cst[i];
			siz[cur] += siz[tar[i]];
			if(hea[cur] == -1 || siz[tar[i]] > siz[hea[cur]])
				hea[cur] = tar[i];
		}
	}

	void dfs2(int cur, int pa)
	{
		top[cur] = pa, ++cnt;
		dfn[cur] = cnt, id[cnt] = cur;

		if(hea[cur] == -1)	return;
		dfs2(hea[cur], pa);

		for(int i = beg[cur]; i; i = nex[i])
			if(tar[i] != hea[cur] && tar[i] != fat[cur])
				dfs2(tar[i], tar[i]);
	}

	#define lson (nod <<1)
	#define rson ((nod <<1) | 1)
	void build(int nod, int lef, int rig)
	{
		if(lef == rig)	seg[nod] = vap[id[lef]];
		else
		{
			int mid = (lef + rig) >> 1;
			build(lson, lef, mid);
			build(rson, mid + 1, rig);
			seg[nod] = seg[lson] * seg[rson];
		}
	}

	inline void init_treecut() {
		memset(hea, -1, sizeof(hea));
		dfs1(1, 0);
		dfs2(1, 1);
		vap[id[1]] = 1;
		build(1, 1, n);
	}

	void update(int nod, int lef, int rig, int goa, Mint val)
	{
		if(lef == rig)	seg[nod] = val;
		else
		{
			int mid = (lef + rig) >> 1;
			if(goa <= mid)	update(lson, lef, mid, goa, val);
			else			update(rson, mid + 1, rig, goa, val);
			seg[nod] = seg[lson] * seg[rson];
		}
	}

	Mint query(int nod, int lef, int rig, int goal, int goar)
	{
		if(goar < lef || rig < goal)	return Mint(1);
		if(goal <= lef && rig <= goar)	return seg[nod];
		Mint ret = 1;
		int mid = (lef + rig) >> 1;
		ret *= query(lson, lef, mid, goal, goar);
		ret *= query(rson, mid + 1, rig, goal, goar);
		return ret;
	}

	Mint query_path(int u, int v)
	{
		Mint ret = 1;
		while(top[u] != top[v])
		{
			if(dep[top[u]] < dep[top[v]])	swap(u, v);
			ret *= query(1, 1, n, dfn[top[u]], dfn[u]);
			u = fat[top[u]];
		}
		if(dfn[u] > dfn[v])	swap(u, v);
		ret *= query(1, 1, n, dfn[u], dfn[v]);
		return ret;
	}

	void update_point(int x, Mint y)
	{
		int u = tar[x << 1], v = tar[x << 1 | 1];
		if(dep[u] < dep[v])	swap(u, v);
		update(1, 1, n, dfn[u], y);
	}

};

Tree<262144, 524288> T;

int main()
{
	read(n), read(m);

	ll x, res;
	for(int i = 1, u, v; i != n; ++i)
	{
		read(u), read(v), read(x);
		T.add_edge(u, v, x);
		T.add_edge(v, u, x);
	}

	T.init_treecut();

	for(int i = 0, a, b, key; i != m; ++i)
	{
		read(key);
		if(key == 1)
		{
			read(a), read(b), read(x);

			if(a == b)	res = 1;
			else		res = T.query_path(a, b).val;

			if(res)	printf("%lld\n", x / res);
			else	puts("0");
		}
		else
		{
			read(a), read(x);
			T.update_point(a, x);
		}
	}
	return 0;
}


#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define LL long long
inline int read(){
    int a=0,fh=1;char c=getchar();
    while(c>57 or c<48){if(c=='-')fh=-1;c=getchar();}
    while(47<c and c<58){
        a=a*10+c-48;
        c=getchar();
    }
    return a*fh;
}
#define MN 200005
int n,q,fa[19][MN],F[MN],dep[MN],Log[MN];
LL v[MN];
struct data{
    int u,v;
    LL c;
}w[MN];
vector<int>edge[MN];
vector<LL>cost[MN];
int Find(int a){
    if(F[a]==a)return a;
    return F[a]=Find(F[a]);
}
void dfs(int x){
    for(int i=1;i<=Log[dep[x]];++i)fa[i][x]=fa[i-1][fa[i-1][x]];
    for(int i=0;i<edge[x].size();++i)
        if(fa[0][x]!=edge[x][i]){
            dep[edge[x][i]]=dep[x]+1;
            fa[0][edge[x][i]]=x;
            if(cost[x][i]==1) F[edge[x][i]]=Find(x);
            v[edge[x][i]]=cost[x][i];
            dfs(edge[x][i]);
        }
}
int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=Log[dep[x]-dep[y]];i>=0;--i)
        if(dep[fa[i][x]]>=dep[y])x=fa[i][x];
    if(x==y)return x;
    for(int i=Log[dep[x]];i>=0;--i)
        if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
    return fa[0][x];
}
signed main(){
    n=read();q=read();
    int a,b;
    LL c;
    int goal=2;
    for(int i=1;i<=n;++i){
        Log[i]=Log[i-1];
        if(i==goal)goal<<=1,Log[i]++;
    }
    for(int i=1;i<n;++i){
        a=read();b=read();c=read();
        w[i].u=a;w[i].v=b;w[i].c=c;
        edge[a].push_back(b);
        edge[b].push_back(a);
        cost[a].push_back(c);
        cost[b].push_back(c);
    }
    for(int i=1;i<=n;++i)F[i]=i;
    dep[1]=1;
    v[1]=1;
    dfs(1);
    int op;
    for(int i=1;i<=q;++i){
        op=read();a=read();b=read();
        if(op==1){
            c=read();
            int lca=LCA(a,b);
            int x=a,y=b;
            while(dep[x]>dep[lca]&&c){
                c/=v[x];
                x=Find(fa[0][x]);
                if(v[x]==1&&x!=1) {cout<<"!!!!"<<endl;return 0;}
            }
            while(dep[y]>dep[lca]&&c){
                c/=v[y];
                y=Find(fa[0][y]);
                if(v[y]==1&&y!=1){cout<<"@@@"<<endl;return 0;}
            }
            printf("%lld\n",c);
        }
        else{
            int x;
            if(fa[0][w[a].u]==w[a].v)x=w[a].u;
                else x=w[a].v;
            v[x]=b;
            if(v[x]==1LL) F[x]=Find(fa[0][x]);
        }
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int getint(){
	int ssum=0,ff=1;char ch;
	for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
	if(ch=='-') ff=-1,ch=getchar();
	for(;isdigit(ch);ch=getchar()) ssum=ssum*10+ch-'0';
	return ssum*ff;
}
const int M=5e5+5;
int n,m,etot=1,head[M],go[M],nex[M],w[M],re[M];
int dep[M],tp[M],fa[M],son[M],siz[M],mx[M],F[M],from[M];

inline void Addedge(int u,int v,int val){
	nex[++etot]=head[u];head[u]=etot;go[etot]=v;w[etot]=val;from[etot]=u;
}

int Getfa(int x){
	return x==F[x]?x:F[x]=Getfa(F[x]);
}
inline void Merge(int x,int y){
	int fax=Getfa(x),fay=Getfa(y);
	F[fax]=fay;
}

void dfs1(int u,int father){
	fa[u]=father;siz[u]=1;dep[u]=dep[father]+1;
	for(int i=head[u];i;i=nex[i]){
		int v=go[i];if(v==father) continue;
		dfs1(v,u);
		if(w[i]==1) Merge(v,u);
		siz[u]+=siz[v];re[v]=w[i];
		if(siz[son[u]]<siz[v]) son[u]=v;
	}
}

void dfs2(int u,int Top){
	tp[u]=Top;
	if(son[u]) dfs2(son[u],Top);
	for(int i=head[u];i;i=nex[i]){
		int v=go[i];if(v==fa[u]||v==son[u]) continue;
		dfs2(v,v);
	}
}

inline int Getlca(int x,int y){
	while(tp[x]!=tp[y]){
		if(dep[tp[x]]>dep[tp[y]]) x=fa[tp[x]];
		else y=fa[tp[y]];
	}
	return dep[x]<dep[y]?x:y;
}

signed main(){
	cin>>n>>m;

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

	for(int i=1,u,v,val;i<n;i++){
		u=getint();v=getint();val=getint();

		Addedge(u,v,val);Addedge(v,u,val);
	}

	dfs1(1,0);dfs2(1,1);

	while(m--){
		int op,x,y,val;
		op=getint();
		if(op==1){
			x=getint();y=getint();val=getint();
			int lca=Getlca(x,y);

			int now=x;
			while(now!=lca){
				if(!val) break;
				if(re[now]==1) now=Getfa(now);
				if(dep[now]<=dep[lca]) break;
				val/=re[now];now=fa[now];
			}

			now=y;
			while(now!=lca){
				if(!val) break;
				if(re[now]==1) now=Getfa(now);
				if(dep[now]<=dep[lca]) break;
				val/=re[now];now=fa[now];
			}

			cout<<val<<"\n";
		}
		else{
			int id=getint();val=getint();
			x=from[id<<1];y=go[id<<1];
			if(dep[x]>dep[y]) swap(x,y);
			re[y]=val;
			if(val==1) Merge(y,x);
		}
	}
	return 0;
}


#define  REP(i, s, e) for (int i = s; i <= e; i++)
#define DREP(i, s, e) for (int i = s; i >= e; i--)
#define DEBUG fprintf(stderr, "Passing [%s] in Line %lld\n", __FUNCTION__, __LINE__)

#define chkmax(a, b) a = max(a, (b))
#define chkmin(a, b) a = min(a, (b))

#include <iostream>
#include <cstdio>
#include <cmath>
#define int long long
#define double long double

using namespace std;
const int maxn = 100000 + 10, maxm = maxn + 10, maxnode = 1700000;
const double inf = 2e18, eps = 1e-8;
int bg[maxn], ne[maxm << 1], to[maxm << 1], w[maxm << 1], e;
void add(int x, int y, int z)
{
	e++;
	to[e] = y;
	ne[e] = bg[x];
	bg[x] = e;
	w[e] = z;
}

template <typename T> T read()
{
	T ans(0), flag(1);
	char c(getchar());
	while (!isdigit(c))
	{
		if (c == '-') flag = -1;
		c = getchar();
	}
	while (isdigit(c))
	{
		ans = ans * 10 + c - 48;
		c = getchar();
	}
	return ans * flag;
}

void file(string s)
{
	freopen((s + ".in").c_str(), "r", stdin);
	freopen((s + ".out").c_str(), "w", stdout);
#ifdef CraZYali
	freopen((s + ".err").c_str(), "w", stderr);
#endif
}

int n, q;

int depth[maxn], siz[maxn], hvy[maxn], fa[maxn];
double W[maxn];

void dfs1(int x)
{
	siz[x] = 1;
	for (int i = bg[x]; i ; i = ne[i])
		if (to[i] ^ fa[x])
		{
			W[to[i]] = w[i];
			fa[to[i]] = x;
			depth[to[i]] = depth[x] + 1;
			dfs1(to[i]);
			siz[x] += siz[to[i]];
			if (siz[to[i]] > hvy[x]) hvy[x] = to[i];
		}
}
int top[maxn], dfn[maxn], dfs_clock, ww[maxn];
void dfs2(int x, int y)
{
	top[x] = y;
	ww[dfn[x] = ++dfs_clock] = W[x];
	if (hvy[x]) dfs2(hvy[x], y);
	for (int i = bg[x]; i ; i = ne[i])
		if (to[i] ^ fa[x] && to[i] ^ hvy[x]) dfs2(to[i], to[i]);
}

#define mid (l + r >> 1)
#define lson ls[p], l, mid
#define rson rs[p], mid + 1, r

int root, ls[maxnode], rs[maxnode], cur;
double mul[maxnode];

void build(int &p, int l, int r)
{
	if (!p) p = ++cur;
	if (l == r) mul[p] = ww[l];
	else
	{
		build(lson);
		build(rson);
		mul[p] = mul[ls[p]] * mul[rs[p]];
	}
}
void pushup(int p, int l, int r)
{
	mul[p] = mul[ls[p]] * mul[rs[p]];
	if (mul[p] > inf) mul[p] = 0;
}
void update(int p, int l, int r, int pos, double val)
{
	if (l == r) mul[p] = val;
	else
	{
		if (pos <= mid) update(lson, pos, val);
		else update(rson, pos, val);
		pushup(p, l, r);
	}
}
double query(int p, int l, int r, int L, int R)
{
	if (L <= l && r <= R) return mul[p];
	else
	{
		double res(1);
		if (L <= mid) res *= query(lson, L, R);
		if (R >  mid) res *= query(rson, L, R);
		return res > inf ? 0 : res;
	}
}
int query(int x, int y, double v)
{
	double res = 1;
	while (top[x] ^ top[y])
	{
		if (depth[top[x]] < depth[top[y]]) swap(x, y);
		res *= query(1, 1, n, dfn[top[x]], dfn[x]) ;
		if (res > v) return 0;
		x = fa[top[x]];
	}
	if (depth[x] > depth[y]) swap(x, y);
	res *= query(1, 1, n, dfn[x], dfn[y]) / W[x];
//	return res;
	return abs(res) < eps ? 0 : floor(v / res);
}
double query(int x, int y)
{
	double res = 1;
	while (top[x] ^ top[y])
	{
		if (depth[top[x]] < depth[top[y]]) swap(x, y);
		res *= query(1, 1, n, dfn[top[x]], dfn[x]);
		x = fa[top[x]];
	}
	if (depth[x] > depth[y]) swap(x, y);
	res *= query(1, 1, n, dfn[x], dfn[y]) / W[x];
	return res;
//	return abs(res) < eps ? 0 : floor(v / res);
}

int X[maxn], Y[maxn], Z[maxn];

signed main()
{
	cin >> n >> q;
	REP(i, 1, n-1)
	{
	    cin >> X[i] >> Y[i] >> Z[i];
		add(X[i], Y[i], Z[i]);add(Y[i], X[i], Z[i]);
	}
	mul[0] = 1;
	depth[1] = 1;
	dfs1(1);
	W[1] = 1;
	dfs2(1, 1);
	build(root, 1, n);
	while (q--)
	{
		int type(read<int>());
		int x, y;double v;
		if (type == 1)
		{
		    cin >> x >> y >> v;
			cout << query(x, y, v) << endl;
		}
		else
		{
		    cin >> x >> v;
			if (fa[X[x]] != Y[x]) swap(X[x], Y[x]);
			W[X[x]] = v;
			update(1, 1, n, dfn[X[x]], v);
		}
		/*
		fputs("--------\n", stderr);
		REP(i, 1, n)
			REP(j, i, n)
			fprintf(stderr, "%lld %lld %.2LF\n", i, j, query(i, j));
			*/
	}
//	while (1);
	return 0;
}


#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string.h>
#include<cmath>
#include<ctime>
#include<complex>
#include<queue>
#define N 101000
#define M 5010
#define eps 1e-5
#define epsd 1e-12
#define INF 1000000000000000010LL
#define mod 998244353
#ifdef WIN32
#define L_L "%lld"
#else
#define L_L "%lld"
#endif
#define LOG 20
using namespace std;
int dep[N],fa[N],pos[N],top[N];
int head[N];
int stack[N][3];
long long w[N<<2],siz[N];
long long fw[N];
bool bid[N<<2];
struct roads{
	int u,v;
}road[N];
int n,q,ap=1,root=1,bp=0,in[N],xu[N];
struct ways{
	int now,next;
	long long w;
}way[N<<1];
inline void link(int u,int v,long long w){
	way[++ap].now=v;way[ap].w=w;way[ap].next=head[u];head[u]=ap;
	way[++ap].now=u;way[ap].w=w;way[ap].next=head[v];head[v]=ap;
}
inline int rd(){
	register int res=0;
	register char ch=getchar();
	register bool flag=false;
	while(ch<'0'||ch>'9'){
		flag=(ch=='-');ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return flag?-res:res;
}
inline long long read(){
	register long long res=0;
	register char ch=getchar();
	register bool flag=false;
	while(ch<'0'||ch>'9'){
		flag=(ch=='-');ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		res=(res<<3LL)+(res<<1LL)+ch-'0';
		ch=getchar();
	}
	return flag?-res:res;
}
inline void DFS(){
	register int i,j,top,x,y,to;
	top=0;
	stack[++top][0]=root=1;
	stack[top][1]=head[root];
	siz[root]=1;dep[root]=1;
	while(top){
		x=stack[top][0];
		y=stack[top][1];
		stack[top][1]=way[y].next;
		if(y==0){
			top--;
			if(pos[fa[x]]==0||siz[pos[fa[x]]]<siz[x]){
				pos[fa[x]]=x;
			}
			siz[fa[x]]+=siz[x];
			continue;
		}
		to=way[y].now;
		if(to==fa[x])continue;
		fa[to]=x;fw[to]=way[y].w;dep[to]=dep[x]+1;
		stack[++top][0]=to;
		stack[top][1]=head[to];
		siz[to]=1;
	}
	::top[root]=root;
	xu[++bp]=root;in[root]=bp;
	stack[++top][0]=root;
	stack[top][1]=head[root];
	stack[top][2]=pos[root]?1:0;
	while(top){
		x=stack[top][0];
		if(stack[top][2]){
			stack[top][2]=0;
			stack[++top][0]=pos[x];
			stack[top][1]=head[pos[x]];
			stack[top][2]=pos[pos[x]]?1:0;
			::top[pos[x]]=::top[x];
			xu[++bp]=pos[x];in[pos[x]]=bp;
			continue;
	  	}
	    y=stack[top][1];
	    if(y==0){
	    	top--;continue;
		}
		stack[top][1]=way[y].next;
		to=way[y].now;if(to==pos[x]||to==fa[x])continue;
		stack[++top][0]=to;
		stack[top][1]=head[to];
		stack[top][2]=pos[to]?1:0;
		::top[to]=to;
		xu[++bp]=to;in[to]=bp;
 	}
}
inline void update(int o){
	if(bid[o<<1]||bid[o<<1|1]){
		bid[o]=1;w[o]=0;return;
	}
	if(INF/w[o<<1]>=w[o<<1|1]){
		w[o]=w[o<<1]*w[o<<1|1];
		bid[o]=0;
	}
	else {
		w[o]=0;bid[o]=1;
	}
}
inline void change(int o,int l,int r,int x,long long ww){
	if(l==r){
		w[o]=ww;bid[o]=0;return;
	}
	int mid=(l+r)>>1;
	if(x<=mid)change(o<<1,l,mid,x,ww);
	else change(o<<1|1,mid+1,r,x,ww);
	update(o);
}
inline void build(int o,int l,int r){
	w[o]=0;bid[o]=0;
	if(l==r){
		if(l==1){
			w[o]=1;bid[o]=0;return;
		}
		w[o]=fw[xu[l]];bid[o]=0;
		return;
	}
	int mid=(l+r)>>1;
	build(o<<1,l,mid);build(o<<1|1,mid+1,r);
	update(o);
}
inline long long ask(int o,int l,int r,int L,int R){
	if(l==L&&r==R){
		if(bid[o])return -1;
		return w[o];
	}
	int mid=(l+r)>>1;
	long long u,v;
	if(R<=mid)return ask(o<<1,l,mid,L,R);
	else if(L>mid)return ask(o<<1|1,mid+1,r,L,R);
	else {
		u=ask(o<<1,l,mid,L,mid);
		if(u==-1)return -1;
		v=ask(o<<1|1,mid+1,r,mid+1,R);
		if(v==-1)return -1;
		if(INF/u>=v)return u*v;
		return -1;
	}
}
inline void lca(int u,int v,long long ww){
	if(u==v) printf(L_L"\n",ww);return;
	long long res;
	bool flagl,flagr;
	while(top[u]!=top[v]){
		flagl=dep[top[u]]<=dep[top[v]];
		flagr=dep[top[v]]<=dep[top[u]];
		if(flagl){
			res=ask(1,1,n,in[top[v]],in[v]);
			if(res==-1) printf("0\n");return;
			ww/=res;
			if(ww==0) printf("0\n");return;
			v=fa[top[v]];
		}
		 if(flagr){
			res=ask(1,1,n,in[top[u]],in[u]);
			if(res==-1){
				printf("0\n");return;
			}

			ww/=res;
			if(ww==0){
				printf("0\n");return;
			}
			u=fa[top[u]];
		}
	}
	if(u==v) printf(L_L"\n",ww);return;
	if(dep[u]<dep[v]) res=ask(1,1,n,in[u]+1,in[v]);
	else  res=ask(1,1,n,in[v]+1,in[u]);
	if(res==-1) printf("0\n");
	else printf(L_L"\n",ww/res);
}
void work(){
    register int i,j,u,v;
    register long long w;
    n=rd();q=rd();
    for(i=1;i<n;i++){
    	road[i].u=u=rd();road[i].v=v=rd();w=read();
    	link(u,v,w);
	}
    DFS();
    build(1,1,n);
    for(i=1;i<=q;i++){
    	j=rd();
    	if(j==1){
    		u=rd();v=rd();lca(u,v,read());
		}
		else {
			u=rd();w=read();
			change(1,1,n,in[dep[road[u].u]>dep[road[u].v]?road[u].u:road[u].v],w);
		}
	}
}
int main(){
	work();
	fclose(stdin);
	fclose(stdout);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int n,m,head[MAXN],tot,dep[MAXN];
int U[MAXN],V[MAXN],father[MAXN];
int dfn[MAXN],ltp[MAXN],pre[MAXN];
int wson[MAXN],siz[MAXN];
LL seg[MAXN<<2],val[MAXN],cnt;
struct edge{int to,nxt;LL paid;}e[MAXN<<1];
void addEdge(int u,int v,LL w){e[++tot]=(edge){v,head[u],w};head[u]=tot;}
void dfs1(int u){
	siz[u]=1;wson[u]=ltp[u]=0;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==father[u])continue;
		dep[v]=dep[u]+1;father[v]=u;val[v]=e[i].paid;
		dfs1(v);siz[u]+=siz[v];
		if(siz[wson[u]]<siz[v])wson[u]=v;
	}
}
void dfs2(int u,int tp){
	dfn[u]=++cnt;pre[cnt]=u;ltp[u]=tp;
	if(wson[u])dfs2(wson[u],tp);
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==father[u]||v==wson[u])
			continue;
		dfs2(v,v);
	}
}
void build(int rt,int l,int r){
	if(l==r)return (void)(seg[rt]=val[pre[l]]);
	int mid=l+r>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	if(1e18/seg[rt<<1]<seg[rt<<1|1])seg[rt]=1e18+1;
	else seg[rt]=seg[rt<<1]*seg[rt<<1|1];
}
void modify(int rt,int l,int r,int ai,LL aw){
	if(l==r)return (void)(seg[rt]=aw);int mid=l+r>>1;
	if(ai<=mid)modify(rt<<1,l,mid,ai,aw);
	else modify(rt<<1|1,mid+1,r,ai,aw);
	if(1e18/seg[rt<<1]<seg[rt<<1|1])seg[rt]=1e18+1;
	else seg[rt]=seg[rt<<1]*seg[rt<<1|1];
}
int query(int rt,int l,int r,int al,int ar){
	if(l>r||al>r||ar<l)return 1;
	if(al<=l&&r<=ar)return seg[rt];
	int mid=l+r>>1;LL res=1;
	if(al<=mid){
		LL tmp=query(rt<<1,l,mid,al,ar);
		if(1e18/res<tmp)res=1e18+1;else res*=tmp;
	}
	if(mid<ar){
		LL tmp=query(rt<<1|1,mid+1,r,al,ar);
		if(1e18/res<tmp)res=1e18+1;else res*=tmp;
	}
	return res;
}
LL Chain_Query(int u,int v){
	if(u==v)return 1;LL res=1;
	for(int fu=ltp[u],fv=ltp[v];fu^fv;u=father[fu],fu=ltp[u]){
		if(dep[fu]<dep[fv])swap(u,v),swap(fu,fv);
		LL tmp=query(1,1,n,dfn[fu],dfn[u]);
		if(1e18/res<tmp)res=1e18+1;else res*=tmp;
	}
	if(dep[u]>dep[v])swap(u,v);
	LL tmp=query(1,1,n,dfn[u]+1,dfn[v]);
	if(1e18/res<tmp)res=1e18+1;else res*=tmp;
	return res;
}
signed main(){
	read(n);read(m);
	for(int i=1;i<n;i++){
		int u,v;LL w;read(u);read(v);read(w);
		addEdge(u,v,w);addEdge(v,u,w);
		U[i]=u;V[i]=v;
	}
	dfs1(1);dfs2(1,1);build(1,1,n);
	for(int i=1;i<=m;i++){
		int opt;read(opt);
		if(opt==1){
			int a,b;LL c;read(a);read(b);read(c);
			printf("%lld\n",c/Chain_Query(a,b));
		}
		else{
			int p;LL c;read(p);read(c);
			modify(1,1,n,max(dfn[U[p]],dfn[V[p]]),c);
		}
	}
	return 0;
}