题目大意:
给出N个关系,每个关系包括一个X,Y,Z,当Z=1时,必须要满足X=Y,当Z=0时,必须要满足X≠Y,问所有的关系是否存在冲突,不存在输出YES,存在输出NO。 给 出 N 个 关 系 , 每 个 关 系 包 括 一 个 X , Y , Z , 当 Z = 1 时 , 必 须 要 满 足 X = Y , 当 Z = 0 时 , 必 须 要 满 足 X ≠ Y , 问 所 有 的 关 系 是 否 存 在 冲 突 , 不 存 在 输 出 Y E S , 存 在 输 出 N O 。
多组数据
1≤N≤106
1
≤
N
≤
10
6
1≤X,Y≤108
1
≤
X
,
Y
≤
10
8
0≤Z≤1
0
≤
Z
≤
1
分析:
显然可以用一个并查集维护,
我们将相等的点存在同一个集合中,当一个
满足X≠Y
满
足
X
≠
Y
的
X,Y
X
,
Y
同时在一个集合中,则有冲突
因为
X,Y
X
,
Y
比较大,可以采用hash或者map
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define modn 1000007
#define N 1000005
using namespace std;
struct Node {
int x, y, z;
}a[N];
int Hash[modn][2], f[modn], cnt;
int Getid(int x) {
int k = x % modn;
while (Hash[k][0] && Hash[k][0] != x) {
k++;
if (k == modn) k = 0;
}
if (!Hash[k][0]) Hash[k][1] = ++cnt;
Hash[k][0] = x;
return k;
}
int Find(int x) {
if (f[x] == x) return x;
f[x] = Find(f[x]);
return f[x];
}
int main() {
int T, n;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 0; i < modn; i++) Hash[i][0] = 0, f[i] = i;
cnt = 0;
bool check = 1;
for (int i = 1; i <= n; i++) {
scanf("%d %d %d", &a[i].x, &a[i].y, &a[i].z);
int idx = Getid(a[i].x);
int idy = Getid(a[i].y);
if (a[i].z == 1) {
int rpx = Find(idx);
int rpy = Find(idy);
f[rpx] = f[rpy];
}
}
for (int i = 1; i <= n; i++) {
if (!check) break;
int idx = Getid(a[i].x);
int idy = Getid(a[i].y);
int rpx = Find(idx);
int rpy = Find(idy);
if (a[i].z == 1 && f[rpx] != f[rpy]) check = 0;
if (a[i].z == 0 && f[rpx] == f[rpy]) check = 0;
}
if (check) printf("YES\n");
else printf("NO\n");
}
return 0;
}