在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。
考虑一个约束满足问题的简化版本:假设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≤n≤1000000
1≤i,j≤1000000000
输入样例:
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
输出样例:
NO
YES
这道题思路并不难,我以为并查集一步到位,后来频频出错。
看了y总的课才知道,我其实越界了,我才明白,我需要进行一个离散化操作。
数据范围
1≤n≤1000000
1≤i,j≤1000000000
然后我们发现i,j其实太过庞大了,我们用离散化的操作进行一个缩小范围。
然后离散化有两个操作:
我们要用到的是第二种操作。
这下思路就简单很多了,看完y总的视频
写的第一个代码
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
unordered_map<int,int> mp;
int idx=0;
const int N=2e6+10;
int p[N];
int get_id(int x)
{
if(mp.count(x)==0) mp[x]=++idx;
return mp[x];
}
int find(int x)
{
if(p[x]==x) return x;
return p[x]=find(p[x]);
}
struct Q
{
int a,b,w;
} q[N];
int main(void)
{
int T;
cin>>T;
while(T--)
{
mp.clear();
idx=0;
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
q[i]={get_id(a),get_id(b),c};
}
for(int i=1;i<=n;i++)
{
if(q[i].w==1)
{
int pa=find(q[i].a);
int pb=find(q[i].b);
p[pa]=pb;
}
}
bool flag=false;
for(int i=1;i<=n;i++)
{
if(q[i].w==0)
{
int pa=find(q[i].a);
int pb=find(q[i].b);
if(pa==pb)
flag=true;
break;
}
}
if(flag) puts("NO");
else puts("YES");
}
}
没有WA,后来仔细想了一下,我忽略了一些条件,如果前面说某某不存在一个区间后面出现了合并,我们无法判断,这是我的代码的缺陷,最终我提出了最终版本,很类似y总的代码了。
成功AC
#include<iostream>
#include<map>
#include<algorithm>
using namespace std;
unordered_map<int,int> mp;
int idx=0;
const int N=2e6+10;
int p[N];
int get_id(int x)
{
if(mp.count(x)==0) mp[x]=++idx;
return mp[x];
}
int find(int x)
{
if(p[x]==x) return x;
return p[x]=find(p[x]);
}
struct Q
{
int a,b,w;
} q[N];
int main(void)
{
int T;
cin>>T;
while(T--)
{
mp.clear();
idx=0;
int n;
cin>>n;
for(int i=1;i<=2*n;i++) p[i]=i;
for(int i=1;i<=n;i++)
{
int a,b,c;
cin>>a>>b>>c;
q[i]={get_id(a),get_id(b),c};
}
for(int i=1;i<=n;i++)
{
if(q[i].w==1)
{
int pa=find(q[i].a);
int pb=find(q[i].b);
p[pa]=pb;
}
}
bool flag=false;
for(int i=1;i<=n;i++)
{
if(q[i].w==0)
{
int pa=find(q[i].a);
int pb=find(q[i].b);
if(pa==pb)
{ flag=true;
break;}
}
}
if(flag) puts("NO");
else puts("YES");
}
}