AcWing 237 程序自动分析 (并查集)
https://www.acwing.com/problem/content/239/
离线,离散化 \(i,j\) 的编号,
先处理 \(x_i = x_j\) 的操作,将 \(i,j\) 合并,
再查询 \(x_i = x_j\) 的操作,看 \(i,j\) 是否在同一个集合里
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1000010;
int T,n;
int op[maxn], u[maxn], v[maxn];
int num[maxn], cnt;
int fa[maxn], ran[maxn];
int find(int x){
int y = x;
while(y != fa[y]){
y = fa[y];
}
return fa[x] = y;
}
void unite(int x, int y){
x = find(x), y = find(y);
if(x == y) return;
if(ran[x] < ran[y]){
fa[x] = y;
}else{
fa[y] = x;
if(ran[x] == ran[y]){
++ran[x];
}
}
}
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
T = read();
for(int i = 1; i <= 2000000; ++i) fa[i] = i;
while(T--){
n = read();
for(int i = 1; i <= cnt; ++i) fa[i] = i;
cnt = 0;
for(int i = 1; i <= n; ++i){
u[i] = read(), v[i] = read(), op[i] = read();
num[++cnt] = u[i], num[++cnt] = v[i];
}
sort(num + 1, num + 1 + cnt);
cnt = unique(num + 1, num + 1 + cnt) - num - 1;
for(int i = 1; i <= n; ++i){
u[i] = lower_bound(num + 1, num + 1 + cnt, u[i]) - num;
v[i] = lower_bound(num + 1, num + 1 + cnt, v[i]) - num;
}
for(int i = 1; i <= n; ++i){
if(op[i]) unite(u[i], v[i]);
}
int flag = 0;
for(int i = 1; i <= n; ++i){
if(!op[i]){
if(find(u[i]) == find(v[i])){
printf("NO\n");
flag = 1;
break;
}
}
}
if(!flag){
printf("YES\n");
}
}
return 0;
}