#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
constexpr int N = 1e5 + 10, mod = 51061;
bool tagrev[N];
int n, m, ch[N][2], fa[N], val[N], sum[N], siz[N], tagmul[N], tagadd[N];
int where(int x) { return ch[fa[x]][1] == x; }
bool isroot(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
void print() {
for (int i = 0; i <= n; i++) cout << i << ": val=" << val[i] << ", sum=" << sum[i] << ", ch=[" << ch[i][0] << ", " << ch[i][1] << "], fa=" << fa[i] << ", tag=[ + " << tagadd[i] << ", * " << tagmul[i] << ", rev " << tagrev[i] << "]" << endl;
}
void pushup(int x) {
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
sum[x] = (sum[ch[x][0]] + val[x] + sum[ch[x][1]]) % mod;
}
void pushdown(int x) {
if (tagrev[x]) {
if (ch[x][0]) swap(ch[ch[x][0]][0], ch[ch[x][0]][1]), tagrev[ch[x][0]] = !tagrev[ch[x][0]];
if (ch[x][1]) swap(ch[ch[x][1]][0], ch[ch[x][1]][1]), tagrev[ch[x][1]] = !tagrev[ch[x][1]];
tagrev[x] = false;
}
val[ch[x][0]] = (val[ch[x][0]] * tagmul[x] % mod + tagadd[x]) % mod;
val[ch[x][1]] = (val[ch[x][1]] * tagmul[x] % mod + tagadd[x]) % mod;
sum[ch[x][0]] = (sum[ch[x][0]] * tagmul[x] % mod + siz[ch[x][0]] * tagadd[x] % mod) % mod;
sum[ch[x][1]] = (sum[ch[x][1]] * tagmul[x] % mod + siz[ch[x][1]] * tagadd[x] % mod) % mod;
tagmul[ch[x][0]] = tagmul[ch[x][0]] * tagmul[x] % mod, tagmul[ch[x][1]] = tagmul[ch[x][1]] * tagmul[x] % mod;
tagadd[ch[x][0]] = (tagadd[ch[x][0]] * tagmul[x] % mod + tagadd[x]) % mod;
tagadd[ch[x][1]] = (tagadd[ch[x][1]] * tagmul[x] % mod + tagadd[x]) % mod;
tagmul[x] = 1, tagadd[x] = 0;
}
void pushdownall(int x) {
if (!isroot(x)) pushdownall(fa[x]);
pushdown(x);
}
void rotate(int x) {
if (isroot(x)) return;
int y = fa[x], z = fa[fa[x]], chk = where(x);
if (!isroot(y)) ch[z][where(y)] = x;
ch[y][chk] = ch[x][chk ^ 1];
if (ch[x][chk ^ 1]) fa[ch[x][chk ^ 1]] = y;
ch[x][chk ^ 1] = y, fa[y] = x, fa[x] = z;
pushup(y), pushup(x);
}
void splay(int x) {
pushdownall(x);
for (int y; y = fa[x], !isroot(x); rotate(x))
if (!isroot(y)) rotate(where(y) == where(x) ? y : x);
}
void access(int x) {
int y = 0;
while (x) {
splay(x);
ch[x][1] = y;
pushup(x);
y = x, x = fa[x];
}
}
void beroot(int x) {
access(x), splay(x);
swap(ch[x][0], ch[x][1]);
tagrev[x] = !tagrev[x];
}
void belink(int x, int y) {
beroot(x);
access(y);
splay(y);
}
int findRoot(int x) {
access(x), splay(x);
while (ch[x][0]) x = ch[x][0];
splay(x);
return x;
}
void link(int x, int y) {
if (findRoot(x) != findRoot(y)) beroot(x), fa[x] = y;
}
void cut(int x, int y) {
belink(x, y);
if (ch[y][0] == x) ch[y][0] = fa[x] = 0;
}
void updatemul(int x, int y, int v) {
belink(x, y);
val[x] = val[x] * v % mod, sum[x] = sum[x] * v % mod, tagmul[x] = tagmul[x] * v % mod, tagadd[x] = tagadd[x] * v % mod;
}
void updateadd(int x, int y, int v) {
belink(x, y);
val[x] = (val[x] + v) % mod, sum[x] = (sum[x] + siz[x] * v % mod) % mod, tagadd[x] = (tagadd[x] + v) % mod;
}
int query(int x, int y) {
belink(x, y);
return sum[y];
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
tagmul[i] = 1;
val[i] = 1;
pushup(i);
}
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
link(u, v);
}
while (m --> 0) {
char opt;
cin >> opt;
if (opt == '+') {
int x, y, v;
cin >> x >> y >> v;
updateadd(x, y, v);
} else if (opt == '-') {
int u1, v1, u2, v2;
cin >> u1 >> v1 >> u2 >> v2;
cut(u1, v1), link(u2, v2);
} else if (opt == '*') {
int x, y, v;
cin >> x >> y >> v;
updatemul(x, y, v);
} else if (opt == '/') {
int u, v;
cin >> u >> v;
cout << query(u, v) << endl;
} else {
int u, v;
cin >> u >> v;
link(u, v);
}
}
return 0;
}