我们把同值的用一个集合表示。
那么我们把同值的先用并查集连起来,最后再判一下不同值的是否不同集合即可。
小优化:用hash表实现离散化,用时间戳避免memset。
代码:
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define g getchar()
using namespace std;
typedef long long ll;
const int N=(1<<21)-1;
template<class o>void qr(o&x) {
char c=g;x=0;int f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=g;}
while(isdigit(c))x=x*10+c-'0',c=g;
x*=f;
}
void write(int x) {
if(x/10)write(x/10);
putchar(x%10+'0');
}
int fa[N],sz[N];
int findfa(int x) {return fa[x]==x?x:fa[x]=findfa(fa[x]);}
void merge(int x,int y) {
if(sz[x]>sz[y])fa[y]=x,sz[x]+=sz[y];
else fa[x]=y,sz[y]+=sz[x];
}
int num[N],nxt[N],len,vis[N],ts;
int find(int x) {
int k=x&N;
if(vis[k]==ts) {
for( ; ;k=nxt[k]) {
if(num[k]==x)return k;
if(nxt[k]==-1)break;
}
while(vis[len]==ts)len++;
nxt[k]=len; k=len++;
}
num[k]=x;nxt[k]=-1;vis[k]=ts;
fa[k]=k;sz[k]=1;
return k;
}
struct no {
int x,y;
}a[N>>1];int tot;
int main() {
int T,n;qr(T);
while(T--) {
qr(n);bool bk=0;
len=0;tot=0;ts++;len=0;
while(n--) {
int x,y,d;qr(x);qr(y);qr(d);
if(bk)continue;
x=findfa(find(x));y=findfa(find(y));
if(d)merge(x,y);
else if(x==y)bk=1;
else a[++tot]=(no){x,y};
}
if(!bk)while(tot) {
int x=a[tot].x,y=a[tot].y;tot--;
if(findfa(x)==findfa(y)) {bk=1; break;}
}
bk?puts("NO"):puts("YES");
}
return 0;
}