const int MAXN=1e5+5,mod=51061;
struct Link_Cut_tree{
int ch[MAXN][2],fa[MAXN],sz[MAXN];
LL w[MAXN],s[MAXN],mul_tag[MAXN],add_tag[MAXN];
int Stack[MAXN],top;
bool flip[MAXN];
void push_up(int id){
s[id]=(s[ch[id][0]]+s[ch[id][1]]+w[id])%mod;
sz[id]=sz[ch[id][0]]+sz[ch[id][1]]+1;
}
void push_add(int id,int v){
s[id]=(s[id]+1LL*v*sz[id])%mod;
w[id]=(w[id]+v)%mod;
add_tag[id]=(add_tag[id]+v)%mod;
}
void push_mul(int id,int v){
s[id]=s[id]*v%mod;
w[id]=w[id]*v%mod;
add_tag[id]=add_tag[id]*v%mod;
mul_tag[id]=mul_tag[id]*v%mod;
}
void push_down(int id){
if(flip[id]){
swap(ch[id][0],ch[id][1]);
flip[ch[id][0]]^=1;
flip[ch[id][1]]^=1;
flip[id]=0;
}
if(mul_tag[id]!=1){
push_mul(ch[id][0],mul_tag[id]);
push_mul(ch[id][1],mul_tag[id]);
mul_tag[id]=1;
}
if(add_tag[id]){
push_add(ch[id][0],add_tag[id]);
push_add(ch[id][1],add_tag[id]);
add_tag[id]=0;
}
}
bool isroot(int id){return ch[fa[id]][0]!=id&&ch[fa[id]][1]!=id;}
void rotate(int id){
int pa=fa[id],ga=fa[pa],dir;
dir=ch[pa][0]==id?0:1;
if(!isroot(pa))ch[ga][ch[ga][0]==pa?0:1]=id;
fa[id]=ga,fa[pa]=id,fa[ch[id][dir^1]]=pa;
ch[pa][dir]=ch[id][dir^1],ch[id][dir^1]=pa;
push_up(pa);push_up(id);
}
void splay(int id){
Stack[top=1]=id;
for(int i=id;!isroot(i);i=fa[i])Stack[++top]=fa[i];
while(top)push_down(Stack[top--]);
while(!isroot(id)){
int pa=fa[id],ga=fa[pa];
if(!isroot(pa))rotate((ch[pa][0]==id)^(ch[ga][0]==pa)?id:pa);
rotate(id);
}
}
void access(int id){
for(int t=0;id;t=id,id=fa[id]){
splay(id);
ch[id][1]=t;
push_up(id);
}
}
void makeroot(int id){access(id);splay(id);flip[id]^=1;}
int findroot(int id){
access(id);splay(id);
push_down(id);
while(ch[id][0])push_down(id=ch[id][0]);
return id;
}
void split(int u,int v){makeroot(u);access(v);splay(v);}
void link(int u,int v){
if(findroot(u)!=findroot(v)){
makeroot(u);
fa[u]=v;
}
}
void cut(int u,int v){
split(u,v);
if(ch[v][0]==u&&ch[u][1]==0){
ch[v][0]=fa[u]=0;
push_up(v);
}
}
void path_add(int u,int v,int val){
split(u,v);
push_add(v,val);
}
void path_mul(int u,int v,int val){
split(u,v);
push_mul(v,val);
}
int path_query(int u,int v){
split(u,v);
return s[v];
}
}LCT;
int main()
{
int n=read_int(),q=read_int(),u,v,c;
_rep(i,1,n)
LCT.w[i]=LCT.s[i]=LCT.sz[i]=1;
_for(i,1,n){
u=read_int(),v=read_int();
LCT.link(u,v);
}
char opt;
while(q--){
opt=get_char();
if(opt=='+'){
u=read_int(),v=read_int(),c=read_int();
LCT.path_add(u,v,c%mod);
}
else if(opt=='-'){
u=read_int(),v=read_int();
LCT.cut(u,v);
u=read_int(),v=read_int();
LCT.link(u,v);
}
else if(opt=='*'){
u=read_int(),v=read_int(),c=read_int();
LCT.path_mul(u,v,c%mod);
}
else{
u=read_int(),v=read_int();
enter(LCT.path_query(u,v));
}
}
return 0;
}