考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include <bits/stdc++.h> using namespace std; const int LEN = 1e6 + 10; int n, tot, fa[LEN], discre[LEN << 1];
struct node { int x_, y_, e_; } arr[LEN];
int find(int x) { if (fa[x] == x) return x; return fa[x] = find(fa[x]); }
void join(int x, int y) { int a = find(x), b = find(y); fa[a] = b; }
void init() { cin >> n; for (int i = 1; i <= n; ++i) { cin >> arr[i].x_ >> arr[i].y_ >> arr[i].e_; discre[tot++] = arr[i].x_, discre[tot++] = arr[i].y_; } sort(discre, discre + tot); tot = unique(discre, discre + tot) - discre; for (int i = 1; i <= n; ++i) { arr[i].x_ = lower_bound(discre, discre + tot, arr[i].x_) - discre + 1; arr[i].y_ = lower_bound(discre, discre + tot, arr[i].y_) - discre + 1; } for (int i = 1; i <= tot; ++i) fa[i] = i; }
void work() { init(); sort(arr + 1, arr + 1 + n, [](node &a, node &b) -> bool { return a.e_ > b.e_; }); for (int i = 1; i <= n; ++i) { if (arr[i].e_) { join(arr[i].x_, arr[i].y_); } else { if (find(arr[i].x_) == find(arr[i].y_)) { cout << "NO" << endl; return; } } } cout << "YES" << endl; }
int main() { int t; cin >> t; while (t--) work(); return 0; }
|
思路
本题不能使用扩展域并查集或边带权并查集,从两个角度分析
边带权并查集
举个例子:
扩展域并查集
举个例子:
1 2 0
2 3 0
也就是1不等于2, 2不等于3
按照扩展域的处理方式,原长度存储相等关系,扩大一倍的长度存储不等关系
那么有{1+n, 2}、{2+n, 1}、{2+n, 3}、{3+n, 2}
合并后的结果为{1+n, 3+n, 2}、{2+n, 1, 3}
可是1和3之间的关系并不能确定啊?你这就把它俩放一个集合了?
正解
首先离散化,1e9的数据范围肯定会炸
通过排序,先处理相等关系,然后再判断不等关系是否与相等关系矛盾即可