rt,#5链的时候寄了
#include <bits/stdc++.h>
#define rg register
#define il inline
#define rep(i,a,b) for(rg int i=(a);i<=(b);++i)
#define sqr(x) ((x)*(x))
using namespace std;
const int INF=0x3f3f3f3f;
inline int read()
{
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
w=(w<<1)+(w<<3)+(ch^48);
ch=getchar();
}
return w*f;
}
inline void write(int x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=100010;
int n,m,a[N],rt;
vector<int> G[N];
int dep[N],sz[N],hson[N],fa[N];
void dfs1(int u,int f)
{
dep[u]=dep[f]+1,sz[u]=1,fa[u]=f;
int hson_sz=-1;
for(int v:G[u])
{
if(v==f) continue;
dfs1(v,u);
sz[u]+=sz[v];
if(hson_sz<sz[v])
{
hson_sz=sz[v];
hson[u]=v;
}
}
}
int top[N],dfn[N],rnk[N],cnt;
void dfs2(int u,int f)
{
top[u]=f,dfn[u]=++cnt,rnk[cnt]=u;
if(!hson[u]) return;
dfs2(hson[u],f);
for(int v:G[u])
{
if(v==hson[u]||v==fa[u]) continue;
dfs2(v,v);
}
}
il int get_son(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
if(fa[top[u]]==v) return top[u];
u=fa[top[u]];
}
if(dep[u]<dep[v]) return hson[v];
else return hson[u];
}
#define ls(p) p<<1
#define rs(p) p<<1|1
const int flag=-1;
struct node
{
int l,r,minn,tag;
node()
{
l=r=0;
tag=flag;
minn=2e9;
}
}tr[N<<2];
void pushup(int p)
{
tr[p].minn=min(tr[ls(p)].minn,tr[rs(p)].minn);
}
void pushdown(int p)
{
if(tr[p].tag!=flag)
{
tr[ls(p)].tag=tr[ls(p)].minn=tr[p].tag;
tr[rs(p)].tag=tr[rs(p)].minn=tr[p].tag;
tr[p].tag=flag;
}
}
void build(int p,int L,int R)
{
tr[p].l=L,tr[p].r=R,tr[p].tag=flag;
if(L==R)
{
tr[p].minn=a[rnk[L]];
return;
}
int mid=(L+R)>>1;
build(ls(p),L,mid);
build(rs(p),mid+1,R);
pushup(p);
}
void update(int p,int L,int R,int k)
{
// if(tr[p].l>R||L>tr[p].r) return;
if(L<=tr[p].l&&tr[p].r<=R)
{
tr[p].minn=tr[p].tag=k;
return;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1;
if(mid>=L) update(ls(p),L,R,k);
if(mid<R) update(rs(p),L,R,k);
pushup(p);
}
int query(int p,int L,int R)
{
if(tr[p].l>R||tr[p].r<L) return 2e9;
if(L<=tr[p].l&&tr[p].r<=R)
{
return tr[p].minn;
}
pushdown(p);
int mid=(tr[p].l+tr[p].r)>>1,minn=2e9;
if(mid>=L) minn=min(minn,query(ls(p),L,R));
if(mid<R) minn=min(minn,query(rs(p),L,R));
return minn;
}
il void update_path(int u,int v,int k)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
{
swap(u,v);
}
update(1,dfn[top[u]],dfn[u],k);
u=fa[top[u]];
}
if(dep[u]<dep[v]) swap(u,v);
update(1,dfn[v],dfn[u],k);
}
il int query_tree(int u)
{
// cout<<u<<endl;
if(u==rt)
{
return query(1,1,n);
}
else if(dfn[rt]>=dfn[u]&&dfn[rt]<=dfn[u]+sz[u]-1)
{
int s=get_son(u,rt);
return min(query(1,1,dfn[s]-1),query(1,dfn[s]+sz[s],n));
}
else return query(1,dfn[u],dfn[u]+sz[u]-1);
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
n=read(),m=read();
for(int i=1,u,v;i<n;++i)
{
u=read(),v=read();
G[u].push_back(v),G[v].push_back(u);
}
for(int i=1;i<=n;++i) a[i]=read();
rt=read();
dfs1(1,0),dfs2(1,1);
build(1,1,n);
for(int i=1,opt,x,y,v;i<=m;++i)
{
opt=read();
if(opt==1)
{
rt=read();
}
else if(opt==2)
{
x=read(),y=read(),v=read();
update_path(x,y,v);
}
else
{
x=read();
printf("%d\n",query_tree(x));
}
}
return 0;
}