/*
start in 14:52:49, september 2nd
wrong answer in 16:13:32 ,september 2nd
wrong answer in 16:18:20 , september 2nd
*/
#include<cstdio>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define Starseven main
#define ll long long
namespace lyt {
void read(int &x){
char ch=getchar();int re=0,op=1;
while(ch<'0'||ch>'9'){if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){re=(re<<3)+(re<<1)+ch-'0';ch=getchar();}
x = re * op;
return ;
}
void read(long long &x){
char ch=getchar();long long re=0,op=1;
while(ch<'0'||ch>'9'){if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){re=(re<<3ll)+(re<<1ll)+ch-'0';ch=getchar();}
x = re * op;
return ;
}
void write(int x){
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
return ;
}//记得自己加空格和换行
void write(long long x){
if(x<0){putchar('-');x=-x;}
if(x>9) write(x/10);
putchar(x%10+'0');
return ;
}//记得自己加空格和换行
int max(int x,int y){return x<y?y:x;}
int min(int x,int y){return x<y?x:y;}
int abs(int x){return x<0?-x:x;}
long long max(long long x,long long y){return x<y?y:x;}
long long min(long long x,long long y){return x<y?x:y;}
long long abs(long long x){return x<0?-x:x;}
double max(double x,double y){return x<y?y:x;}
double min(double x,double y){return x<y?x:y;}
double abs(double x){return x<0?-x:x;}
void swap(int &a,int &b) {a ^= b ^= a ^= b;}
void swap(long long &a,long long &b) {a ^= b ^= a ^= b;}
ll Power(ll a, ll b, ll p) {
ll re = 1;
while(b) {
if(b & 1ll) re = (re * a) % p;
b >>= 1ll;
a = (a * a) % p;
}
return re;
}
int Power(int a, int b, int p) {
int re = 1;
while(b) {
if(b & 1) re = 1ll * re * a % p;
b >>= 1;
a = 1ll * a * a % p;
}
return re;
}
}using namespace lyt;
const int N = 4e6 + 20;
int n, tail[N], cot, cnt, root, Lca[N][20];
ll va[N];
struct mp {
int next, to;
}fp[N << 1];
struct Cut {
int id, dep, size, wson, fa, top;
}t[N];
struct seg {
ll minn, tag;
}tr[N << 2];
void Maketo(int from, int to) {
fp[++cot].next = tail[from];
fp[cot].to = to;
tail[from] = cot;
return ;
}
struct segment_tree {
#define ls (id << 1)
#define rs (id << 1 | 1)
#define mid (l + r >> 1)
#define check (x <= l && y >= r)
void Pushup(int id) {
tr[id].minn = min(tr[ls].minn, tr[rs].minn);
return ;
}
void Pushdown(int id) {
if(!tr[id].tag) return ;
tr[ls].minn = tr[id].tag;
tr[rs].minn = tr[id].tag;
tr[ls].tag = tr[id].tag;
tr[rs].tag = tr[id].tag;
tr[id].tag = 0;
return ;
}
void Build_tree(int l, int r, int id) {
if(l == r) {
tr[id].minn = va[l];
tr[id].tag = 0;
return ;
}
Build_tree(l, mid, ls);
Build_tree(mid + 1, r, rs);
Pushup(id);
}
void Change(int l, int r, int x, int y, int id, ll k) {
if(check) {
tr[id].minn = k;
tr[id].tag = k;
return ;
}
Pushdown(id);
if(x <= mid) Change(l, mid, x, y, ls, k);
if(y > mid) Change(mid + 1, r, x, y, rs, k);
Pushup(id);
}
ll Find(int l, int r, int x, int y, int id) {
if(check) return tr[id].minn;
Pushdown(id);
ll minn = 99999999999999;
if(x <= mid) minn = min(minn, Find(l, mid, x, y, ls));
if(y > mid) minn = min(minn, Find(mid + 1, r, x, y, rs));
return minn;
}
#undef ls
#undef rs
#undef mid
#undef check
}tree;
struct Tree_cut {
void Dfs1(int x, int fa) {
t[x].fa = fa;
t[x].dep = t[fa].dep + 1;
t[x].size = 1;
for (int i = tail[x]; i; i = fp[i].next) {
int y = fp[i].to;
if(y == fa) continue;
Lca[y][0] = x;
for (int j = 1; j <= 20; j++)
Lca[y][j] = Lca[ Lca[y][j - 1] ][j - 1];
Dfs1(y, x);
if(!t[x].wson || t[ t[x].wson ].size < t[y].size)
t[x].wson = y;
t[x].size += t[y].size;
}
return ;
}
void Dfs2(int x, int tp) {
t[x].id = ++cnt;
t[x].top = tp;
if(!t[x].wson) return ;
Dfs2(t[x].wson, tp);
for (int i = tail[x]; i; i = fp[i].next) {
int y = fp[i].to;
if(y == t[x].fa) continue;
if(y == t[x].wson) continue;
Dfs2(y, y);
}
}
int Get_Lca(int u, int v) {
if(t[u].dep < t[v].dep)
swap(u, v);
for (int i = 20; i >= 0; i--)
if(t[ Lca[u][i] ].dep > t[v].dep)
u = Lca[u][i];
return u;
}
void Change(int u, int v, ll k) {
while(t[u].top != t[v].top) {
if(t[ t[u].top ].dep < t[ t[v].top ].dep)
swap(u, v);
tree.Change(1, n, t[ t[u].top ].id, t[u].id, 1, k);
u = t[ t[u].top ].fa;
}
if(t[u].dep > t[v].dep)
swap(u, v);
tree.Change(1, n, t[u].id, t[v].id, 1, k);
return ;
}
}cut;
int Starseven(void) {
// freopen("P3979_10.in","r",stdin);
// freopen("P3979.in","w", stdout);
int m;
read(n);
read(m);
for (int i = 1; i < n; i++) {
int u, v;
read(u);
read(v);
Maketo(u, v);
Maketo(v, u);
}
cut.Dfs1(1, 0);
cut.Dfs2(1, 1);
for (int i = 1; i <= n; i++) {
read(va[ t[i].id ]);
}
tree.Build_tree(1, n, 1);
read(root);
while(m--) {
int opt;
read(opt);
if(opt == 1)
read(root);
else if(opt == 2) {
int p1, p2;
ll v;
read(p1);
read(p2);
read(v);
cut.Change(p1, p2, v);
}
else {
int x;
read(x);
if(x == root) {
write(tr[1].minn);
puts("");
continue;
}
else if(root == 1) {
write(tree.Find(1, n, t[x].id, t[x].id + t[x].size - 1, 1));
puts("");
continue;
}
else if(t[x].id < t[root].id && t[root].id <= t[x].id + t[x].size - 1) {
x = cut.Get_Lca(root, x);
ll ans = 9999999999999999;
ans = min(ans, tree.Find(1, n, 1, t[x].id - 1, 1));
ans = min(ans, tree.Find(1, n, t[x].id + t[x].size, n, 1));
write(ans);
puts("");
continue;
}
else {
write(tree.Find(1, n, t[x].id, t[x].id + t[x].size - 1, 1));
puts("");
continue;
}
}
}
return 0;
}