程序自动分析(BZOJ 4195)
Description
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。
考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。
现在给出一些约束满足问题,请分别对它们进行判定。
Input
输入文件的第1行包含1个正整数t,表示需要判定的问题个数。注意这些问题之间是相互独立的。
对于每个问题,包含若干行:
第1行包含1个正整数n,表示该问题中需要被满足的约束条件个数。
接下来n行,每行包括3个整数i,j,e,描述1个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e=1,则该约束条件为xi=xj;若e=0,则该约束条件为xi≠xj。
Output
输出文件包括t行。
输出文件的第k行输出一个字符串“YES”或者“NO”(不包含引号,字母全部大写),“YES”表示输入中的第k个问题判定为可以被满足,“NO”表示不可被满足。
Sample Input
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
2
1 2 1
1 2 0
2
1 2 1
2 1 1
Sample Output
NO
YES
YES
HINT
在第一个问题中,约束条件为:x1=x2,x1≠x2。这两个约束条件互相矛盾,因此不可被同时满足。
在第二个问题中,约束条件为:x1=x2,x2=x1。这两个约束条件是等价的,可以被同时满足。
1≤n≤1000000
1≤i,j≤1000000000
思路:
并查集很好做,关键是加上离散化
因为数据规模(1e9)很大,超过了数组的上限。但数据据量(1e6) 开数组是刚刚好的
于是我们通过离散排序去重,只把数之间的关系表示出来即可
code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int Mx=1000010;
struct node {
int x,y;
}ok[Mx],no[Mx];
int n,fa[Mx],num[Mx<<1],sated[Mx];
int Find(int x) {
return x==fa[x]?x:fa[x]=Find(fa[x]);
}
int lisa() {
int len=0;sated[++len]=num[1];
for(int i=2;i<=2*n;++i) {
if(num[i]!=num[i-1])
sated[++len]=num[i];
}
return len;
}
int serch(int val,int l,int r) {
int mid=(l+r)>>1;
if(sated[mid]==val) return mid;
else if(sated[mid]<val) return serch(val,mid+1,r);
else return serch(val,l,mid);
}
int main()
{
int T;
scanf("%d",&T);
while(T--) {
int lok=0,lno=0;
for(int i=1;i<=Mx;++i) fa[i]=i;
scanf("%d",&n);
for(int i=1;i<=n;++i) {
int u,v,cas;
scanf("%d%d%d",&u,&v,&cas);
num[i]=u,num[i+n]=v;
if(cas) ok[++lok].x=u,ok[lok].y=v;
else no[++lno].x=u,no[lno].y=v;
}
sort(num+1,num+1+n+n);
int l=lisa();
for(int i=1;i<=lok;++i) {
int a=ok[i].x,b=ok[i].y;
fa[Find(serch(a,1,l))]=Find(serch(b,1,l));
}
bool flag=0;
for(int i=1;i<=lno;++i) {
int a=no[i].x,b=no[i].y;
if(Find(serch(a,1,l))==Find(serch(b,1,l))) {
flag=1;
break;
}
}
if(flag) printf("NO\n");
else printf("YES\n");
memset(ok,0,sizeof(ok));
memset(no,0,sizeof(no));
}
return 0;
}
从0到1很难,但从1到100很容易