【BZOJ4195】[Noi2015]程序自动分析 并查集
【BZOJ4195】[Noi2015]程序自动分析
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
题解:并查集
由于相等关系有传递性,不相等关系无传递性,我们就可以先不管不等关系,按相等关系建立并查集,然后判断不等关系是否成立就行了
本题需要离散化
#include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int maxn=1000010; int n,m; int x[maxn],y[maxn],e[maxn],f[maxn<<1]; struct node { int num,org,k; }s[maxn<<1]; int find(int x){return (f[x]==x)?x:(f[x]=find(f[x]));} int readin() { int ret=0; char gc=getchar(); while(gc<'0'||gc>'9') gc=getchar(); while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret; } bool cmp(node a,node b) { return a.num<b.num; } void work() { m=readin(); int i; for(i=1;i<=m;i++) { x[i]=readin(),y[i]=readin(),e[i]=readin(); s[i*2-1].num=x[i],s[i*2].num=y[i]; s[i*2-1].org=s[i*2].org=i; s[i*2-1].k=0,s[i*2].k=1; } sort(s+1,s+2*m+1,cmp); int pre=0,n=0; for(i=1;i<=2*m;i++) { if(pre<s[i].num) pre=s[i].num,n++; if(!s[i].k) x[s[i].org]=n; else y[s[i].org]=n; } for(i=1;i<=n;i++) f[i]=i; for(i=1;i<=m;i++) if(e[i]&&find(x[i])!=find(y[i])) f[f[x[i]]]=f[y[i]]; for(i=1;i<=m;i++) { if(!e[i]&&find(x[i])==find(y[i])) { printf("NO\n"); return ; } } printf("YES\n"); return ; } int main() { int T=readin(); while(T--) work(); }
| 欢迎来原网站坐坐! >原文链接<