#include <iostream>
#include <vector>
using namespace std;
#define se second
#define fi first
#define pb push_back
const int N = 100010;
typedef pair<int, int> PII;
struct edge{
int v, w;
};
vector<edge> e[N];
PII edges[N];
int dep[N], fa[N], top[N], sz[N], idx, id[N], son[N];
int ww[N], nw[N];
struct node{
int l, r, mx, add, ass;
}tr[N * 4];
void dfs1(int u, int f){
dep[u] = dep[f] + 1, fa[u] = f, sz[u] = 1;
for(auto &[v, w]: e[u]){
if(v == f) continue;
ww[v] = w;
dfs1(v, u);
sz[u] += sz[v];
if(sz[son[u]] < sz[v]) son[u] = v;
}
}
void dfs2(int u, int t){
id[u] = ++ idx, nw[idx] = ww[u], top[u] = t;
if(son[u]) dfs2(son[u], t);
for(auto &[v, w]: e[u]){
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
void pushup(int u){
tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
}
void pushdown(int u){
int &add = tr[u].add, &ass = tr[u].ass;
if(ass >= 0){
tr[u << 1].mx = tr[u << 1 | 1].mx = ass;
tr[u << 1].ass = tr[u << 1 | 1].ass = ass;
tr[u << 1].add = tr[u << 1 | 1].add = 0;
ass = -1, add = 0;
}
else if(add){
tr[u << 1].mx += add, tr[u << 1 | 1].mx += add;
tr[u << 1].add += add, tr[u << 1 | 1].add += add;
add = 0;
}
}
void build(int u, int l, int r){
tr[u] = {l, r, nw[l], 0, -1};
if(l == r) return;
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void modify(int u, int l, int r, int add, int ass){
if(l > r) return;
if(l <= tr[u].l && tr[u].r <= r){
if(ass >= 0) tr[u].mx = tr[u].ass = ass, tr[u].add = 0;
else tr[u].mx += add, tr[u].add += add;
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify(u << 1, l, r, add, ass);
else modify(u << 1 | 1, l, r, add, ass);
pushup(u);
}
void modify_path(int u, int v, int add, int ass){
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u, v);
modify(1, id[top[u]], id[u], add, ass);
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
modify(1, id[v] + 1, id[u], add, ass);
}
int query(int u, int l, int r){
if(l > r) return 0;
if(l <= tr[u].l && tr[u].r <= r) return tr[u].mx;
pushdown(u);
int res = 0;
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) res = query(u << 1, l, r);
if(r > mid) res = max(res, query(u << 1 | 1, l, r));
return res;
}
int query_path(int u, int v){
int res = 0;
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u, v);
res = max(res, query(1, id[top[u]], id[u]));
u = fa[top[u]];
}
if(dep[u] < dep[v]) swap(u, v);
res = max(res, query(1, id[v] + 1, id[u]));
return res;
}
int main(){
int n;
cin >> n;
for(int i = 1; i < n; i++){
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
e[u].pb({v, w}), e[v].pb({u, w});
edges[i] = {u, v};
}
dfs1(1, 0), dfs2(1, 1);
build(1, 1, n);
while(1){
char op[10];
int k, u, v, w;
scanf("%s", op);
if(op[0] == 'S') break;
else if(op[0] == 'M'){
scanf("%d%d", &u, &v);
printf("%d\n", query_path(u, v));
}
else if(op[1] == 'h'){
scanf("%d%d", &k, &w);
if(dep[edges[k].fi] > dep[edges[k].se]) u = edges[k].fi;
else u = edges[k].se;
modify(1, id[u], id[u], 0, w);
}
else{
scanf("%d%d%d", &u, &v, &w);
if(op[0] == 'A') modify_path(u, v, w, -1);
else modify_path(u, v, 0, w);
}
}
return 0;
}