#include<bits/stdc++.h>
using namespace std;
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
const int maxn=2e5+10;
struct edge
{
int next,v;
}e[2*maxn];
struct point
{
int l,r,minx,lazy;
}tree[4*maxn];
int rt,n,q,r,a[maxn],cnt,head[maxn*2],f[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],num,ri[maxn];
void add(int u,int v)
{
num++;
e[num].v=v;
e[num].next=head[u];
head[u]=num;
}
void dfs1(int u,int fa,int depth)
{
f[u]=fa;
d[u]=depth;
size[u]=1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==fa)continue;
dfs1(v,u,depth+1);
size[u]+=size[v];
if(size[v]>size[son[u]] || !son[u])
{
son[u]=v;
}
}
}
void dfs2(int u,int t)
{
top[u]=t;
id[u]=++cnt;
rk[cnt]=u;
ri[u]=cnt;
if(!son[u])return;
dfs2(son[u],t);
ri[u]=max(ri[u],ri[son[u]]);
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(v!=son[u]&&v!=f[u])
{
dfs2(v,v);
ri[u]=max(ri[u],ri[v]);
}
}
}
void build(int p,int l,int r)
{
int mid=(l+r)>>1;
tree[p].l=l;
tree[p].r=r;
if(l==r)
{
tree[p].minx=a[rk[mid]];
return;
}
build(ls(p),l,mid);
build(rs(p),mid+1,r);
tree[p].minx=min(tree[ls(p)].minx,tree[rs(p)].minx);
}
void pushdown(int p)
{
int w = tree[p].lazy;
if(w && tree[p].l!= tree[p].r)
{
tree[ls(p)].lazy = w;
tree[rs(p)].lazy = w;
tree[ls(p)].minx = w;
tree[rs(p)].minx = w;
}
tree[p].minx;
}
int query(int p,int l,int r)
{
if(tree[p].l>=l&&tree[p].r<=r)
{
return tree[p].minx;
}
pushdown(p);
int mid=(tree[p].l+tree[p].r)>>1;
int s=2147483647;
if(l<=mid)
{
s=min(query(ls(p),l,r),s);
}
if(r>mid)
{
s=min(query(rs(p),l,r),s);
}
return s;
}
void change(int p,int l,int r,int x)
{
if(tree[p].l>=l&&tree[p].r<=r)
{
tree[p].minx=x;
tree[p].lazy = x;
return;
}
pushdown(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid)
{
change(ls(p),l,r,x);
}
if(r>mid)
{
change(rs(p),l,r,x);
}
tree[p].minx=min(tree[ls(p)].minx,tree[rs(p)].minx);
}
void update(int x,int y,int w)
{
int fx=top[x],fy=top[y];
while (fx != fy)
{
if(d[x] > d[y])
{
change(1,id[fx],id[x],w);
x=f[fx];
fx=top[x];
}else
{
change(1,id[fy],id[y],w);
y=f[fy];
fy=top[y];
}
}
if(d[x]>d[y])swap(x,y);
//change(1,id[x],id[y],w);
}
bool check(int x,int rt)
{
if(rt==x)
{
return 1;
}
if(rt==1)
{
return 0;
}
return check(x,f[rt]);
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int m;
cin>>n>>m;
for(int i=1;i<=n-1;i++)
{
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
cin>>rt;
for(int i=1;i<=m;i++)
{
int op;
cin>>op;
if(op == 1)
{
cin>>rt;
}else if(op == 2)
{
int x,y,v;
cin>>x>>y>>v;
update(x,y,v);
}else{
int x;
cin>>x;
if(x==rt)
{
cout<<query(1,1,n)<<endl;
}else if(check(x,rt))
{
if(ri[rt]==ri[x])cout<<query(1,id[x],id[rt]-1)<<endl;
else cout<<min(query(1,id[x],id[rt]-1),query(1,ri[rt]+1,ri[x]))<<endl;
}else
{
cout<<query(1,id[x],ri[x])<<endl;
}
}
}
return 0;
}