算法:离散化+并查集
难度:NOIP
首先,易证(数据范围:10^9那么大,如果开一个10^9的fa数组的话,空间肯定超限),此题需要离散化----->方法
all in all,离散化有三步:
1.排序
2.去重(可以用到unique去重函数)
3.二分索引(可以用到lower_bound函数)
离散化之后,将e=1的情况(等式)直接添加到并查集中,之后枚举检验不等式是否成立即可,对于它约束的两个变量,如果在一个集合里面,那就不可能满足!如不相等的约束条件都满足,那就YES。
注意:
- fa数组要开2*n辣么大(因为离散化后,有辣么多的数数呀)
- 记得给fa数组赋初值
- 记得要请数组
- unique之前一定要先排序,因为它处理的是相邻元素的重复元素。---> 详解
(仿佛一点也不详)
代码如下:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#define ll long long
#define N 100005
using namespace std;
struct node
{
int x,y,e;
}a[N];
int lsh[N<<1],fa[N<<1];//因为离散化之后的大小是2*n
int cmp(node a,node b)
{
return a.e>b.e;
}
int findf(int x)
{
if(x==fa[x]) return x;
return fa[x]=findf(fa[x]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int cnt=0;
memset(a,0,sizeof(a));
memset(lsh,0,sizeof(lsh));
memset(fa,0,sizeof(fa));
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].e);
lsh[++cnt]=a[i].x;
lsh[++cnt]=a[i].y;
}
sort(lsh+1,lsh+1+cnt);
int uni=unique(lsh+1,lsh+1+cnt)-lsh;//unique之前要先排序,因为它处理的是相邻元素的重复元素
for(int i = 1;i <= n;i++)
{
a[i].x=lower_bound(lsh,lsh+uni,a[i].x)-lsh;
a[i].y=lower_bound(lsh,lsh+uni,a[i].y)-lsh;
}
for(int i = 1;i <= uni;i++)
{
fa[i]=i;
}
sort(a+1,a+n+1,cmp);
int flag=1;
for(int i = 1;i <= n;i++)
{
int r1=findf(a[i].x);
int r2=findf(a[i].y);
if(a[i].e)
{
fa[r1]=r2;
}else if(r1==r2)
{
puts("NO");
flag=0;
break;
}
}
if(flag) puts("YES");
}
return 0 ;
}