题目描述:
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。考虑一个约束满足问题的简化版本:假设 x1,x2,x3,…
代表程序中出现的变量,给定 n 个形如 xi=xj 或 xi≠xj 的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,
使得上述所有约束条件同时被满足。
例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。
现在给出一些约束满足问题,请分别对它们进行判定。
输入格式
输入文件的第 1 行包含 1 个正整数 t,表示需要判定的问题个数,注意这些问题之间是相互独立的。
对于每个问题,包含若干行:
第 1 行包含 1 个正整数 n,表示该问题中需要被满足的约束条件个数。
接下来 n 行,每行包括 3 个整数 i,j,e,描述 1 个相等/不等的约束条件,相邻整数之间用单个空格隔开。若 e=1,则该约束条件为 xi=xj;若 e=0,则该约束条件为 xi≠xj
输出格式
输出文件包括 t 行。输出文件的第 k 行输出一个字符串 YES 或者 NO,YES 表示输入中的第 k 个问题判定为可以被满足,NO 表示不可被满足。
数据范围
1≤t≤10 !(http://)
1≤n≤105
1≤i,j≤109
解决这个问题的思路:
1.首先要确定什么时候会出现不可被满足的情况
这个很好考虑:应该是当需要同时满足x1 == x2 以及x1 != x2时会出现不可被满足的情况
因此可以用一个并查集先维护一些需要保证两两之间必须相等的变量,再遍历一遍不等关系,
一旦发现一对不等关系(如x1 != x2)出现在了相等关系中(即x1和x2出现在并查集的同一个连通块内),那么条件不可以被满足
2.实现的细节:
对于相等关系以及不等关系,我们可以都先用vector<PII>eq和vector<PII>ne将其存储起来。
由于题目中i和j的取值都是达到10^9,因此要考虑离散化,这里可以用一个unordered_map<int, int>rec,
rec中的first存储x的下标值,而rec中的second存储此x下标值在并查集p中对应的位置,通俗的将就是rec[num]就可以访问到下标的num的x在并查集中的位置
具体的实现代码如下:
`
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<unordered_map>
using namespace std;
typedef pair<int, int> PII;
//路径压缩的并查集查找函数
int findX(vector<int>& p, int x){
if(p[x] != x) p[x] = findX(p, p[x]);
return p[x];
}
int main(){
int t;
scanf("%d", &t);
while(t -- ){
int n, cnt = 0;//cnt用于记录在相等以及不等关系中一共需要用到多少个不同的数
vector<PII>eq;
vector<PII>ne;
vector<int>p;
unordered_map<int, int>rec;//映射记录一个x的下标 以及它在并查集中的位置
scanf("%d", &n);
while(n -- ){
int a, b, s;
scanf("%d%d%d", &a, &b, &s);
if(s == 0){//不等关系
ne.push_back({a, b});
}else{//相等关系
eq.push_back({a, b});
}
if(!rec.count(a)) rec[a] = cnt++;
if(!rec.count(b)) rec[b] = cnt++;
}
p.assign(cnt, 0);
for(int i = 0; i < cnt; i++) p[i] = i;//初始化并查集
for(int i = 0; i < eq.size(); i++){
int a = eq[i].first, b = eq[i].second;
int fa = rec[a], fb = rec[b];//进行映射 将数ab映射到并查集上
int pa = findX(p, fa), pb = findX(p, fb);
p[pa] = pb;
}
bool res = true;
for(int i = 0; i < ne.size(); i++){
int a = ne[i].first, b = ne[i].second;
int fa = rec[a], fb = rec[b];
if(findX(p, fa) == findX(p, fb)){
res = false;
break;
}
}
if(res) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
`