思路: 只有最多2n个变量,所以为每个变量分配编号,并用编号进行并查集
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<map>
#include<stdio.h>
using namespace std;
map<int, int> mp;//记录超级大数对应的编号
int f[2000200];
int fd(int x) {//查找
return (f[x] == x) ? (x) : (f[x] = fd(f[x]));
}
void hb(int x, int y) {//合并(迫真命名
int _x = fd(x), _y = fd(y);
if (_x != _y) f[_x] = _y;
}
int cw = 0;
class nd {
public:
int a, b;
nd() {
a = 0; b = 0;
}
nd(int _1, int _2) {
a = _1; b = _2;
}
};
nd com[2000200];
void nc(int x, int y) {
com[cw++] = nd(x, y);
}
void m1() {
cw = 0;
mp.clear();
int w = 1;
int n;
scanf("%d", &n);
for (int i = 0; i <= 2*n + 10; i++) {
f[i] = i;
}
int _1, _2, _3;
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &_1, &_2, &_3);
if (_3) {//加入:为新数据分配一个编号,并用编号进行并查集
map<int, int>::iterator l = mp.find(_1);
map<int, int>::iterator r = mp.find(_2);
if (l==mp.end()) {
mp[_1] = w++;
l = mp.find(_1);
}
if (r == mp.end()) {
mp[_2] = w++;
r = mp.find(_2);
}
//printf("1\n");
hb(l->second, r->second);
}
else {
if (_1 == _2) {//自己和自己不同就干掉
printf("NO\n");
return;
}
nc(_1, _2);
}
}
for (int i = 0; i < cw; i++) {
map<int, int>::iterator l2 = mp.find(com[i].a);
map<int, int>::iterator r2 = mp.find(com[i].b);
if (l2 == mp.end() || r2 == mp.end()) continue;
//printf("2\n");
if (fd(l2->second) == fd(r2->second)) {//干掉!
printf("NO\n"); return;
}
}
printf("YES\n");
return;
}
int main() {
int t;
//freopen("1.in", "r", stdin);//好大的测试数据啊
scanf("%d", &t);
for (int i = 0; i < t; i++) {
m1();
}
return 0;
}