#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define N 10010 #define INF 0x7f7f7f7f #define MAX(a,b) (((a)>(b))?(a):(b)) #define MIN(a,b) (((a)<(b))?(a):(b)) struct hh { int v,w,next,num; }edges[N<<1]; struct segtree { int maxx,minn,delta; }tree[N<<2]; int T,n,son[N],dep[N],fa[N],val[N],hash[N],from[N],size[N],top[N],point[N],a,b,tid[N],num[N],en,end; char str[100]; int flag; inline void init() { memset(point,0xff,sizeof(point)); en=-1;end=0;a=b=0; } inline void addedge(int u,int v,int w,int num) { edges[++en].next=point[u]; point[u]=en; edges[en].v=v; edges[en].w=w; edges[en].num=num; edges[++en].next=point[v]; point[v]=en; edges[en].v=u; edges[en].w=w; edges[en].num=num; } inline void dfs(int x) { size[x]=1;son[x]=0; for(int i=point[x];i!=-1;i=edges[i].next) if(edges[i].v!=fa[x]) { fa[edges[i].v]=x; dep[edges[i].v]=dep[x]+1; from[edges[i].v]=i; dfs(edges[i].v); if(size[edges[i].v]>size[son[x]])son[x]=edges[i].v; size[x]+=size[edges[i].v]; } } inline void make(int x,int anc) { tid[x]=++end;val[end]=edges[from[x]].w;hash[edges[from[x]].num]=end;top[x]=anc; if(son[x]!=0)make(son[x],anc); for(int i=point[x];i!=-1;i=edges[i].next) if(edges[i].v!=fa[x]&&edges[i].v!=son[x]) make(edges[i].v,edges[i].v); } inline void negative(int x) { int tmp=tree[x].maxx; tree[x].maxx=-tree[x].minn; tree[x].minn=-tmp; } inline void push_up(int x) { tree[x].maxx=MAX(tree[x<<1].maxx,tree[x<<1^1].maxx); tree[x].minn=MIN(tree[x<<1].minn,tree[x<<1^1].minn); } inline void push_down(int x) { if(tree[x].delta) { tree[x<<1].delta^=1; tree[x<<1^1].delta^=1; negative(x<<1); negative(x<<1^1); tree[x].delta=0; } } inline void build(int x,int l,int r) { if(l==r) { tree[x].maxx=tree[x].minn=val[l]; tree[x].delta=0; return; } int mid=l+r>>1; build(x<<1,l,mid); build(x<<1^1,mid+1,r); push_up(x); tree[x].delta=0; } inline void update(int x,int l,int r,int left,int right,int delta) { if(l>=left&&r<=right) { if(!flag)tree[x].maxx=tree[x].minn=delta; if(flag) { tree[x].delta^=1; negative(x); } return; } int mid=l+r>>1; push_down(x); if(left<=mid)update(x<<1,l,mid,left,right,delta); if(right>mid)update(x<<1^1,mid+1,r,left,right,delta); push_up(x); } inline int query(int x,int l,int r,int left,int right) { if(l>=left&&r<=right)return tree[x].maxx; int mid=l+r>>1,tmp1=-INF,tmp2=-INF; push_down(x); if(left<=mid)tmp1=query(x<<1,l,mid,left,right); if(right>mid)tmp2=query(x<<1^1,mid+1,r,left,right); push_up(x); return MAX(tmp1,tmp2); } inline void change(int x,int y) { int f1=top[x],f2=top[y]; while(f1!=f2) { if(dep[f1]<dep[f2]){swap(f1,f2);swap(x,y);} update(1,1,end,tid[f1],tid[x],0); x=fa[f1];f1=top[x]; } if(x==y)return; if(dep[x]>dep[y])swap(x,y); update(1,1,end,tid[son[x]],tid[y],0); } inline int ask(int x,int y) { if(x==y)return 0; int f1=top[x],f2=top[y],res=-INF,tmp; while(f1!=f2) { if(dep[f1]<dep[f2]){swap(x,y);swap(f1,f2);} tmp=query(1,1,end,tid[f1],tid[x]); res=MAX(res,tmp); x=fa[f1];f1=top[x]; } if(x==y)return res; if(dep[x]>dep[y])swap(x,y); tmp=query(1,1,end,tid[son[x]],tid[y]); return MAX(res,tmp); } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); init(); for(int i=1;i<n;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w,i); } dep[1]=0; dfs(1); make(1,1); build(1,1,end); while(1) { scanf(" %s",str); if(str[0]=='D')break; scanf("%d%d",&a,&b); if(str[0]=='C')flag=0,update(1,1,end,hash[a],hash[a],b); if(str[0]=='Q')printf("%d\n",ask(a,b)); if(str[0]=='N')flag=1,change(a,b); } } return 0; }