#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<map>
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define a_all a.begin(),a.end()
using namespace std;
typedef long long ll;
vector<int> v;
namespace hikari {
int n,m,num[100010],w[100010];
bool vis[100010];
int nw[100010];
//int b[400010];
struct tr {
int l,r;
int add=0,chg=0,mx=-1;
} tree[400010];
void build(int p,int l,int r) {
tree[p]={l,r,0,0,nw[r]};
if(l==r)
return;
int mid=l+r>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);
//tree[p].l=l,tree[p].r=r;
}
/*int get(int p,int l,int r) {
if(l<=tree[p].l&&tree[p].r<=r)
return tree[p].sum;
int mid=tree[p].l+tree[p].r>>1,res=0;
if(tree[p].add) {
tree[p<<1].sum=tree[p].add*(tree[p<<1].r-tree[p<<1].l+1);
tree[p<<1|1].sum=tree[p].add*(tree[p<<1|1].r-tree[p<<1|1].l+1);
tree[p<<1].add=tree[p].add,tree[p<<1|1].add=tree[p].add;
tree[p].add=0;
}
if(l<=mid) res+=get(p<<1,l,r);
if(r>mid) res+=get(p<<1|1,l,r);
return res;
}*/
void ptr_change(int p,int l,int r,int k) {
if(tree[p].l==tree[p].r) {
tree[p].mx=k;
tree[p].add=k;
return;
}
int mid=tree[p].l+tree[p].r>>1;
if(l<=mid) ptr_change(p<<1,l,r,k);
else ptr_change(p<<1|1,l,r,k);
tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);
}
int mxing(int p,int l,int r) {
if(l<=tree[p].l&&tree[p].r<=r)
return tree[p].mx;
int mid=tree[p].l+tree[p].r>>1,mxr=-2e9;
if(l<=mid) mxr=max(mxr,mxing(p<<1,l,r));
if(r>mid) mxr=max(mxr,mxing(p<<1|1,l,r));
return mxr;
}
/*void update(int p,int l,int r,int k) {
if(l<=tree[p].l&&tree[p].r<=r) {
tree[p].sum+=k*(tree[p].r-tree[p].l+1);
tree[p].add+=k;
return;
}
int mid=tree[p].l+tree[p].r>>1;
if(tree[p].add) {
int k = tree[p].add;
tree[p<<1].sum+=k*(tree[p<<1].r-tree[p<<1].l+1);
tree[p<<1|1].sum+=k*(tree[p<<1|1].r-tree[p<<1|1].l+1);
tree[p<<1].add+=k,tree[p<<1|1].add+=k;
tree[p].add=0;
}
if(l<=mid) update(p<<1,l,r,k);
if(r>mid) update(p<<1|1,l,r,k);
tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}*/
//treepow
const int N = 100010;
vector<int> e[N];
int r,p;
int top[N],dep[N],fa[N]={0,1},id[N],hson[N],siz[N]={0},cnt;
int dfs1(int x,int fat) {
if(vis[x]) return siz[x];
vis[x]=1;
hson[x]=0;
dep[x]=dep[fat]+1;
fa[x]=fat;
siz[x]=1,siz[hson[x]]=0;
for(int v:e[x]) {
if(v==fa[x]) continue;
siz[x]+=dfs1(v,x);
if(siz[v]>siz[hson[x]])
hson[x]=v;
}
return siz[x];
}
void dfs2(int u,int t) {
if(vis[u]) return;
vis[u]=1;
top[u]=t;
id[u]=++cnt;
nw[cnt]=w[u];
if(!hson[u]) return;
dfs2(hson[u],t);
for(int v:e[u]) {
if(v==t||v==hson[u]) continue;
else dfs2(v,v);
}
}
/*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+=get(1,id[top[u]],id[u]);
u=fa[top[u]];
}
if(dep[u]<dep[v]) swap(u,v);
res+=get(1,id[v],id[u]);
return res;
}*/
int query_mx(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,mxing(1,id[top[u]],id[u]));
u=fa[top[u]];
}
if(dep[u]<dep[v]) swap(u,v);
res=max(res,mxing(1,id[v]+1,id[u]));
return res;
}
/*void update_path(int u,int v,int k) {
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(1,id[top[u]],id[u],k);
u=fa[top[u]];
}
if(dep[u]<dep[v]) swap(u,v);
update(1,id[v],id[u],k);
}*/
void change_path(int u,int v,int k) {
if(dep[u]<dep[v]) swap(u,v);
ptr_change(1,id[u],id[u],k);
}
void update_tree(int u,int k) {
// update(1,id[u],id[u]+siz[u]-1,k);
}
int query_tree(int u) {
// return get(1,id[u],id[u]+siz[u]-1);
return 0;
}
};
using namespace hikari;
int t;
map<int,pair<int,int>> mp;
int main() {
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--) {
cin>>n;
rep(i,1,n-1) {
int a,b,c;
cin>>a>>b>>c;
e[a].push_back(b);
e[b].push_back(a);
mp[i]={a,b};
w[b]=c;
}
memset(vis,0,sizeof(vis));
dfs1(1,1);
memset(vis,0,sizeof(vis));
dfs2(1,1);
build(1,1,n);
rep(i,1,100010) {
string s;
int a,b;
cin>>s;
if(s=="DONE") break;
else if(s=="QUERY") {
cin>>a>>b;
cout<<query_mx(a,b)<<endl;
} else {
cin>>a>>b;
change_path(mp[a].first,mp[a].second,b);
}
}
}
return 0;
}