在实现程序自动分析的过程当中,经常须要断定一些约束条件是否能被同时知足。node
考虑一个约束知足问题的简化版本:假设x1,x2,x3...表明程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请断定是否能够分别为每个变量赋予恰当的值,使得上述全部约束条件同时被知足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x4≠x1,这些约束条件显然是不可能同时被知足的,所以这个问题应断定为不可被知足。c++
如今给出一些约束知足问题,请分别对它们进行断定。git
输入格式:数组
从文件prog.in中读入数据。ide
输入文件的第1行包含1个正整数t,表示须要断定的问题个数。注意这些问题之间是相互独立的。函数
对于每一个问题,包含若干行:spa
第1行包含1个正整数n,表示该问题中须要被知足的约束条件个数。接下来n行,每行包括3个整数i,j,e,描述1个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e=1,则该约束条件为xi=xj;若�e=0,则该约束条件为xi≠xj;code
输出格式:blog
输出到文件 prog.out 中。
输出文件包括t行。
输出文件的第 k行输出一个字符串“ YES” 或者“ NO”(不包含引号,字母所有大写),“ YES” 表示输入中的第k个问题断定为能够被知足,“ NO” 表示不可被知足。
上次写完并查集后孟神又让写的并查集题,题目理解不难,只要先将全部须要判等的约束条件作完,那么当约束条件为0时,咱们只须要查询他们是否被约束过判等的条件,和并查集维护依赖关系的性质很是类似,因此咱们能够用并查集来写这个题;
但等等;妹主席说过不看数据范围写题就是在对本身耍流氓;
那咱们就能够写个离散化啦,感谢Millope教个人离散化;
排序+去重+二分索引(lower—bound函数);
可是须要注意要将全部的约束相等条件先作完,因此咱们将约束为1的排在0以前;
还须要注意的每次咱们要将father数组清零,不然下一次find能够会出错;
#include<bits/stdc++.h> using namespace std; #define N 200010 template<typename T>inline void read(T &x) { x=0;T f=1,ch=getchar(); while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x*=f; } int father[N],n,m,flag; inline int find(int x){return father[x]==x?x:father[x]=find(father[x]);} struct node { int x, y, z; }a[N]; bool cmp(node a, node b){return a.z>b.z;} int sizeb=0,b[N]; int main() { read(n); for(int i=1;i<=n;i++) { flag=1;sizeb=0; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(father,0,sizeof(father)); read(m); for(int j=1;j<=m;j++) { read(a[j].x);read(a[j].y);read(a[j].z); b[++sizeb]=a[j].x; b[++sizeb]=a[j].y; } sort(b+1,b+sizeb+1); sizeb=unique(b+1,b+sizeb+1)-b-1; for(int i=1;i<=m;++i) { a[i].x=lower_bound(b+1,b+sizeb+1,a[i].x)-b; a[i].y=lower_bound(b+1,b+sizeb+1,a[i].y)-b; } for(int i=1;i<=sizeb;i++) { father[i]=i; } sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { int p=find(a[i].x),q=find(a[i].y); if(a[i].z) father[p]=q; else if(p==q) { printf("NO\n"); flag=0; break; } } if(flag) printf("YES\n"); } return 0; }