AcWing 237. 程序自动分析
题目传送门
本题目主要是学习无序离散化+并查集,原因是:
并查集无法开到\(1e9\)的大小,但输入的数字比较稀疏,可以使用无序离散化unordered_map可以将每个输入的数字映射到一个小的范围内,就可以开这样大的数组进行并查集啦~
#include
using namespace std;
const int N = 2000010;
int n, m;
//结构体
struct Query {
int x, y, e;
} query[N];
//无序离散化
unordered_map S;
int get(int x) {
if (S.count(x) == 0) S[x] = ++n; // x映射为第n个数字
return S[x];
}
//最简并查集
int p[N];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]); //路径压缩
return p[x];
}
int main() {
int T;
cin >> T;
while (T--) {
//多组测试数据,需要每次从头开始,清空
n = 0;
S.clear();
cin >> m;
// m组数据全部读入,通过get计算离散化后的对应的位置号(指并查集数组的位置)
for (int i = 0; i < m; i++) {
int x, y, e;
cin >> x >> y >> e;
query[i] = {get(x), get(y), e};
}
for (int i = 1; i <= n; i++) p[i] = i;
// 合并所有相等约束条件
for (int i = 0; i < m; i++)
if (query[i].e == 1) {
int pa = find(query[i].x), pb = find(query[i].y);
p[pa] = pb;
}
// 检查所有不等条件
bool has_conflict = false;
for (int i = 0; i < m; i++)
if (query[i].e == 0) {
int pa = find(query[i].x), pb = find(query[i].y);
if (pa == pb) {
has_conflict = true;
break;
}
}
if (has_conflict)
puts("NO");
else
puts("YES");
}
return 0;
}