/*
求不含某个点的链的重要度最大值,支持修改(包括撤销某次修改)。
树链剖分,对于每个区间维护两个个优先队列,一个是添加的,一个是撤销的。
有一个问题是如何合并区间,代码巧妙地避开了这个棘手的问题,只修改不合并,但是查询时是单点查询,且从上往下查的,所以时刻维护最大值就可以了。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#define N 100010
using namespace std;
int head[N],fa[N],dep[N],dfn[N],son[N],top[N];
int n,m,x[N*2],y[N*2],z[N*2],tot;
struct node{int v,pre;}e[N*2];
vector<pair<int,int> >stk;
struct Heap{
priority_queue<int> a,b;
void del(int x){b.push(x);}
void push(int x){a.push(x);}
int top(){
while(!b.empty()&&a.top()==b.top()) a.pop(),b.pop();
if(a.empty()) return -1;
return a.top();
}
}t[N*4];
void add(int i,int u,int v){
e[i].v=v;e[i].pre=head[u];head[u]=i;
}
void dfs1(int x){
son[x]=1;
for(int i=head[x];i;i=e[i].pre){
if(e[i].v==fa[x]) continue;
fa[e[i].v]=x;
dep[e[i].v]=dep[x]+1;
dfs1(e[i].v);
son[x]+=son[e[i].v];
}
}
void dfs2(int x,int chain){
dfn[x]=++tot;top[x]=chain;int k=0;
for(int i=head[x];i;i=e[i].pre){
if(e[i].v==fa[x]) continue;
if(son[e[i].v]>son[k]) k=e[i].v;
}
if(!k) return;
dfs2(k,chain);
for(int i=head[x];i;i=e[i].pre){
if(e[i].v==fa[x]||e[i].v==k) continue;
dfs2(e[i].v,e[i].v);
}
}
void modify(int k,int l,int r,int x,int y,int val,int flag){
if(x>y) return;
if(l>=x&&r<=y){
if(flag) t[k].push(val);
else t[k].del(val);
return;
}
int mid=l+r>>1;
if(x<=mid) modify(k*2,l,mid,x,y,val,flag);
if(y>mid) modify(k*2+1,mid+1,r,x,y,val,flag);
}
void updata(int x,int y,int val,int flag){
stk.clear();
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
stk.push_back(make_pair(dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
stk.push_back(make_pair(dfn[y],dfn[x]));
sort(stk.begin(),stk.end());
x=1;
for(int i=0;i<stk.size();i++){
modify(1,1,n,x,stk[i].first-1,val,flag);
x=stk[i].second+1;
}
modify(1,1,n,x,n,val,flag);
}
int query(int k,int l,int r,int x){
if(l==r) return t[k].top();
int mid=l+r>>1;
if(x<=mid) return max(t[k].top(),query(k*2,l,mid,x));
return max(t[k].top(),query(k*2+1,mid+1,r,x));
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
add(i*2-1,u,v);add(i*2,v,u);
}
dfs1(1);dfs2(1,1);
for(int i=1;i<=m;i++){
int tp;scanf("%d",&tp);
if(tp==0){
scanf("%d%d%d",&x[i],&y[i],&z[i]);
updata(x[i],y[i],z[i],1);
}
if(tp==1){
scanf("%d",&x[i]);
updata(x[x[i]],y[x[i]],z[x[i]],0);
}
if(tp==2){
scanf("%d",&x[i]);
printf("%d\n",query(1,1,n,dfn[x[i]]));
}
}
return 0;
}