程序自动分析【离散化+并查集】
NOI2015
、BZOJ4195
、ACwing237
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
const int N = 200000;
int father[N + 5],a[N + 5],b[N + 5]; //分别用来存储离散化后每个结点的代标结点、初始输入点、去重后的点
int n,k_a,k_b; //n如题,
vector<pii> v0,v1; //相等的组、不相等的组
int find_f(int x){ //找到祖先结点/集合中的代表结点
if(father[x] == x)
return x;
return father[x] = find_f(father[x]); //缩短路径
}
void discrete(){ //离散化
sort(a + 1,a + k_a + 1);
b[++k_b] = a[1];
for(int i = 2;i <= k_a;++i){
if(a[i] != a[i - 1])
b[++k_b] = a[i];
}
}
int find_w(int x){ //找到离散化后代替值x的数。
return lower_bound(b + 1,b + k_b + 1,x) - b;
}
void solve(){
k_a = k_b = 0;v0.clear();v1.clear(); //每次都要初始化一下
for(int i = 1;i <= N;++i) //初始化father数组
father[i] = i;
cin>>n;
int x,y,z;
for(int i = 1;i <= n;++i){
cin>>x>>y>>z;
a[++k_a] = x;a[++k_a] = y;
if(z)
v1.push_back(pii(x,y)); //z等于1的时候要合并的情况
else
v0.push_back(pii(x,y)); //z等于0的时候要查询的情况
}
discrete(); //离散化
//合并
for(vector<pii>::iterator it = v1.begin();it != v1.end();++it){
father[find_f(find_w(it->first))] = find_f(find_w(it->second));
}
//查询
for(vector<pii>::iterator it = v0.begin();it != v0.end();++it){
if(find_f(find_w(it->first)) == find_f(find_w(it->second))) {
cout << "NO\n";
return;
}
}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int tt;
cin>>tt;
while(tt--)
solve();
return 0;
}