#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define TR(i,v)         for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i)
#define DEBUG(x)        cout << #x << " = " << x << endl;
#define SIZE(p)         (int)(p).size()
#define MP(a, b)        make_pair((a), (b))
#define ALL(p)          (p).begin(), (p).end()
#define rep(i, n)       for(int (i)=0; (i)<(int)(n); ++(i))
#define REP(i, a, n)    for(int (i)=(a); (i)<(int)(n); ++(i))
#define FOR(i, a, b)    for(int (i)=(int)(a); (i)<=(int)(b); ++(i))
#define FORD(i, b, a)   for(int (i)=(int)(b); (i)>=(int)(a); --(i))
#define CLR(x, y)       memset((x), (y), sizeof((x)))
typedef long long LL;
typedef pair<int, int> pii;
const int inf = ~0U>>1;
const int maxn = 100005;
struct Edge {
	int u,v,w;
}E[maxn];
vector<int> g[maxn];
const int SIZE = 100005;
int top[SIZE],fa[SIZE],dep[SIZE],sz[SIZE],pos[SIZE],posx[SIZE],dfstime;
int W[SIZE];
inline int getit(int u,int v) {
	return dep[u]>dep[v] ? u : v;
}
void dfs1(int u,const vector<int> g[]) {
	dep[u]=dep[fa[u]]+1, sz[u]=1;
    for(size_t i=0;i<g[u].size();++i) {
        int v=g[u][i];
        if(v==fa[u])    continue;
        fa[v]=u;
        dfs1(v,g);
        sz[u]+=sz[v];
    }
}
void dfs2(int u,const vector<int> g[]) {
	posx[dfstime]=u,pos[u]=dfstime++;
	int son=-1;
	for(size_t i=0;i<g[u].size();++i) {
		int v=g[u][i];
		if(v==fa[u])	continue;
		if(son==-1 || sz[v]>sz[son])	son=v;
	}
	if(~son)
		top[son]=top[u], dfs2(son,g);
	for(size_t i=0;i<g[u].size();++i) {
		int v=g[u][i];
		if(v==fa[u] || v==son)	continue;
		top[v]=v, dfs2(v,g);
	}
}
void build(int n,int rt,const vector<int> g[]) {
    fa[rt]=top[rt]=SIZE-1;  dfstime=dep[SIZE-1]=0;
    dfs1(rt,g);
    dfs2(rt,g);
}
struct SegTree {
	static const int maxn = 10005;
	struct Node {
		int l,r,maxv;		
	}v[maxn<<2];
	inline void pushup(int x) {
		v[x].maxv=max(v[x<<1].maxv,v[x<<1|1].maxv);
	}
	void build(int l,int r,int x=1) {
		v[x].l=l,v[x].r=r;
		if(l==r) {
			v[x].maxv=W[posx[l]];
			return;
		}
		int m=(l+r)>>1;
		build(l,m,x<<1), build(m+1,r,x<<1|1);
		pushup(x);
	}
	void update(int pos,int y,int x=1) {
		if(v[x].l==v[x].r) {
			v[x].maxv=y;
			return;
		}
		int m=(v[x].l+v[x].r)>>1;
		if(pos<=m)	update(pos,y,x<<1);
		else		update(pos,y,x<<1|1);
		pushup(x);
	}
	int query(int l,int r,int x=1) {
		if(l<=v[x].l && v[x].r<=r)
			return v[x].maxv;
		int res=-inf, m=(v[x].l+v[x].r)>>1;
		if(l<=m)	res=max(res,query(l,r,x<<1));
		if(r>m)		res=max(res,query(l,r,x<<1|1));
		return res;
	}
}tr;
int ask(int u,int v) {
	int topu=top[u],topv=top[v];
	int res=-inf;
	for(;topu!=topv;u=fa[topu],topu=top[u]) {
		if(dep[topu]<dep[topv])	swap(u,v),swap(topu,topv);
		res=max(res,tr.query(pos[topu],pos[u]));
	}
	if(pos[u]<pos[v])	swap(u,v);
	res=max(res,tr.query(pos[v]+1,pos[u]));
	return res;
}
void change(int u,int v,int y) {
	u=getit(u,v);
	W[u]=y;
	tr.update(pos[u],y);
}
int main(int argc, char const *argv[]) {
#ifndef ONLINE_JUDGE
    freopen("QTREE.in", "r", stdin);
    // freopen("out", "w", stdout);
#endif
    // ios::sync_with_stdio(false);		cin.tie(0);
    int T;	scanf("%d", &T);
    while(T--) {
    	int n;	scanf("%d", &n);
    	rep(i,n)	g[i].clear();
    	FOR(k,1,n-1) {
    		int u,v,w;	scanf("%d%d%d", &u,&v,&w);  --u,--v;
    		E[k]=(Edge){u,v,w};
    		g[u].push_back(v), g[v].push_back(u);
    	}
    	dfstime=0;
    	int rt=rand()%n;
    	rt=0;
        build(n,rt,g);
        FOR(k,1,n-1) {
        	int u=E[k].u,v=E[k].v;
        	W[getit(u,v)]=E[k].w;
        }
        tr.build(1,n-1);
        static char op[30];
        for(;scanf("%s",op)==1 && op[0]!='D';) {
        	int x,y;	scanf("%d%d",&x,&y);
        	if(op[0]=='Q') {
        		--x,--y;
        		int res=ask(x,y);
        		printf("%d\n",res);
        	}else if(op[0]=='C') {
        		int u=E[x].u,v=E[x].v;
        		change(u,v,y);
        	}
        }
    }
    return 0;
}
