题目简述:给你一些变量之间的相等或不等的关系,问是否这些条件可以被同时满足。
题目思路:刚开始时觉得是使用带权并查集去维护这些变量之间的关系,但是这是有问题的,因为不等关系不具备传递性,即a!=b,b!=c,无法确定a和c的关系,所以无法使用带权并查集,仔细想想发现应该是先将所有的相等关系拿出来用并查集维护,然后再处理不等,例如a!=b,找到a和b所在的集合,如果二者所在的集合是同一个那么输出NO,当所有的不等关系也都满足时,输出YES。由于此题的n只有1e5,而变量角标可能很大,所以应当使用离散化。
以下为参考代码:
#include<iostream>
#include<math.h>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
struct da {
long long val;
int id;
}olda[N<<1];
bool cmp(da a, da b)
{
return a.val < b.val;
}
int newa[N << 1];
int s[N << 1];
struct node {
int x, y, re;
}a[N];
bool cmp2(node a, node b)
{
return a.re > b.re;
}
void init()
{
for (int i = 1; i < N * 2; i++)
{
s[i] = i;
}
}
int findset(int x)
{
if (x != s[x])
{
s[x] = findset(s[x]);
}
return s[x];
}
void merge(int a, int b)
{
int roota = findset(a);
int rootb = findset(b);
if (roota != rootb)
{
s[roota] = rootb;
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
init();
int n;
cin >> n;
int i = 0, j = 0;
for (int k = 1; k <= n; k++)
{
cin >> olda[++i].val;
olda[i].id = i;
cin >> olda[++i].val;
olda[i].id = i;
cin >> a[k].re;
}
sort(olda + 1, olda + i + 1, cmp);
int tmp = 1;
for (int k = 1; k <= i; k++)
{
newa[olda[k].id] = tmp;
tmp++;
if (olda[k].val == olda[k - 1].val)
{
tmp--;
newa[olda[k].id] = newa[olda[k-1].id];
}
}
int t = 0;
for (int k = 1; k <= n; k++)
{
a[k].x = newa[++t];
a[k].y = newa[++t];
}
sort(a + 1, a + n + 1, cmp2);
int flag = 0;
for (int i = 1; i <= n; i++)
{
int x = a[i].x;
int y = a[i].y;
if (a[i].re == 1)
{
merge(x, y);
}
else
{
if (findset(x) == findset(y))
{
flag = 1;
break;
}
}
}
if (flag == 0)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
}