#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=3e6;
int sortTmp[MAXN],sortTmpN=0;//离散化
int fa[MAXN];//并查集
void merge(int i,int j){//merge j to i
while(i!=fa[i]){
i=fa[i];
fa[i]=fa[fa[i]];
}
while(j!=fa[j]){
j=fa[j];
fa[j]=fa[fa[j]];
}
fa[j]=i;
}
int getFa(int i){
while(fa[fa[i]]!=fa[i])fa[i]=fa[fa[i]];
return fa[i];
}
struct SingleSet{
int i,j,type;
}setsZero[MAXN],setsOne[MAXN];
int setZeroN=0,setOneN=0;
int findNum(int value){
return lower_bound(sortTmp+1,sortTmp+sortTmpN+1,value)-sortTmp;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(sortTmp,0,sizeof(sortTmp));
memset(fa,0,sizeof(fa));
setZeroN=0;
setOneN=0;
sortTmpN=0;
int n;
scanf("%d",&n);
bool notOk=0;
for(int QWQ=1;QWQ<=n;QWQ++){
int i,j,type;
scanf("%d%d%d",&i,&j,&type);
if(i==j&&type==1)continue;
if(i==j&&type==0){
notOk=1;
}
if(type==0){
setsZero[++setZeroN].i=i,setsZero[setZeroN].j=j,setsZero[setZeroN].type=type;
}else if(type==1){
setsOne[++setOneN].i=i,setsOne[setOneN].j=j,setsOne[setOneN].type=type;
}
sortTmp[++sortTmpN]=i;
sortTmp[++sortTmpN]=j;
}
if(notOk){
cout<<"NO"<<endl;
continue;
}
sort(sortTmp+1,sortTmp+sortTmpN+1);
int newN=unique(sortTmp+1,sortTmp+sortTmpN+1)-(sortTmp+1);
sortTmpN=newN;
for(int i=1;i<=sortTmpN;i++){
fa[i]=i;
}
for(int i=1;i<=setOneN;i++){
int newI=findNum(setsOne[i].i),newJ=findNum(setsOne[i].j);
if(setsOne[i].type==1){
merge(newI,newJ);
}
}
for(int i=1;i<=setZeroN;i++){
int newI=findNum(setsZero[i].i),newJ=findNum(setsZero[i].j);
if(setsZero[i].type==0){
if(getFa(newI)==getFa(newJ)){
cout<<"NO"<<endl;
notOk=true;
break;
}
}
}
if(notOk)continue;
else{
cout<<"YES"<<endl;
continue;
}
}
return 0;
}
sortSet的时候RE了,就先处理1,再处理0