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
");
					flag = 1;
					break;
				}
			}
		}
		
		if(!flag){
			printf("YES
");
		}
	}
	
	return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/13954682.html