Question
张纸条,上面写着三个整数
。
- 若
表示
和
为朋友。
- 否则表示其为敌人。
朋友的朋友也是朋友,问是否有矛盾的情况?
Solution
离散化 并查集
矛盾的情况为既是朋友又是敌人,很容易想到利用并查集去处理这里的关系。
"牛可乐的手下有 1e9 个"这句话是告诉我们直接开数组是要MLE的,结合数据范围以及题意,发现与数据的绝对大小无关,至于他们的相对顺序有关,故进行数据离散化预处理。
- 离散化
- 将关系为朋友的合并
- 查询关系为敌人的是否为朋友
坑点:数组要开>2e6,记得清空vector。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e6 + 5;
const int N = 2e6 + 5;
int n,f[N],a[N],b[N],c[N];
vector<int>V(N);
inline void init(int x) {for(int i=0;i<=x;i++) f[i]=i;}
inline int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
inline void merge(int x,int y){
int u=find(x),v=find(y);
if(u!=v) f[v]=u;
}
inline void discreate(){
V.clear();
for(int i=1;i<=n;i++){
V.push_back(a[i]);
V.push_back(b[i]);
}
sort(V.begin(),V.end());
V.erase(unique(V.begin(),V.end()), V.end());
}
inline int query(int x){
return lower_bound(V.begin(), V.end(), x)-V.begin();
}
void solve(){
cin>>n;
bool flag=true;
for(int i=1;i<=n;i++){cin>>a[i]>>b[i]>>c[i];}
discreate();
init(V.size());
for(int i=1;i<=n;i++){
if(c[i]==1) merge(query(a[i]),query(b[i]));
else{
if(find(query(a[i]))!=find(query(b[i]))) continue;
flag=false;
break;
}
}
cout<<(flag?"YES":"NO")<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
京公网安备 11010502036488号