题目描述
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。
考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。
例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。
现在给出一些约束满足问题,请分别对它们进行判定。
样例
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
NO
YES
离散化+并查集
先把要处理的和要查询的数值存下来,然后离散化一下,最后利用并查集查询答案,这题不难,代码写起来也比较简单,但是可以练一练并查集
时间复杂度
$O(Tn)$
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch & 15);
ch = getchar();
}
return x * f;
}
int f[N];
inline int find(int x) {
if (f[x] == x) return x;
return f[x] = find(f[x]);
}
inline void unio(int u, int v) {
int fa1 = find(u), fa2 = find(v);
if (fa1 != fa2) f[fa1] = fa2;
}
inline bool query(int u, int v) {
if (find(u) == find(v)) return false;
return true;
}
typedef pair<int, int> PII;
vector<PII> modifies, queries;
vector<int> copies;
inline void work() {
int n; cin >> n;
for (int i = 1; i <= n; ++i) {
int co = read(), co_ = read(), opt = read();
if (opt) { modifies.push_back({co, co_}); }
else { queries.push_back({co, co_}); }
}
for (int i = 0; i < modifies.size(); ++i) {
copies.push_back(modifies[i].first);
copies.push_back(modifies[i].second);
}
for (int i = 0; i < queries.size(); ++i) {
copies.push_back(queries[i].first);
copies.push_back(queries[i].second);
}
int m = unique(copies.begin(), copies.end()) - copies.begin() - 1;
sort(copies.begin(), copies.end());
for (int i = 0; i < modifies.size(); ++i) {
modifies[i].first = lower_bound(copies.begin(), copies.end(), modifies[i].first) - copies.begin() + 1;
modifies[i].second = lower_bound(copies.begin(), copies.end(), modifies[i].second) - copies.begin() + 1;
}
for (int i = 0; i < queries.size(); ++i) {
queries[i].first = lower_bound(copies.begin(), copies.end(), queries[i].first) - copies.begin() + 1;
queries[i].second = lower_bound(copies.begin(), copies.end(), queries[i].second) - copies.begin() + 1;
}
for (int i = 1; i <= copies.size(); ++i) {
f[i] = i;
}
for (int i = 0; i < modifies.size(); ++i) {
unio(modifies[i].first, modifies[i].second);
}
for (int i = 0; i < queries.size(); ++i) {
int u = queries[i].first, v = queries[i].second;
if (!query(u, v)) {
puts("NO");
return;
}
}
puts("YES");
}
inline void clear() {
modifies.clear();
queries.clear();
copies.clear();
}
int main() {
int T; cin >> T;
while (T--) {
work();
clear();
}
return 0;
}