原题:node
在实现程序自动分析的过程当中,经常须要断定一些约束条件是否能被同时知足。ui
考虑一个约束知足问题的简化版本:假设x1,x2,x3...表明程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请断定是否能够分别为每个变量赋予恰当的值,使得上述全部约束条件同时被知足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x4≠x1,这些约束条件显然是不可能同时被知足的,所以这个问题应断定为不可被知足。spa
如今给出一些约束知足问题,请分别对它们进行断定。code
输入格式:blog
从文件prog.in中读入数据。字符串
输入文件的第1行包含1个正整数t,表示须要断定的问题个数。注意这些问题之间是相互独立的。get
对于每一个问题,包含若干行:string
第1行包含1个正整数n,表示该问题中须要被知足的约束条件个数。接下来n行,每行包括3个整数i,j,e,描述1个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e=1,则该约束条件为xi=xj;若�e=0,则该约束条件为xi≠xj;it
输出格式:io
输出到文件 prog.out 中。
输出文件包括t行。
输出文件的第 k行输出一个字符串“ YES” 或者“ NO”(不包含引号,字母所有大写),“ YES” 表示输入中的第k个问题断定为能够被知足,“ NO” 表示不可被知足。
带权并查集。
有点相似于食物链,点这里。没作过的同窗能够去作一下加深理解。
咱们用0和1表明这个数和根节点相同或者不一样,当矛盾时即这句话是假话。
因而快乐地写完代码过样例,交了上去:
黑人问号脸(???)
因而下载了数据,发现了这个问题:
若是按照正常的顺序处理,当给出这样的数据时:
a≠b,b≠c,c≠a
根据咱们的理论,0表明相同,1表明不相同,前两个数据能够得:a为0,b为1,c为0,那么当c≠a时,推出矛盾。
这样作显然是错误的。前两个条件并非第三个结论的充要条件。轻易能够举出反例:
a = 1,b = 2,c = 3
那么咱们最好的作法即是先把全部的相等条件加入到同一个并查集中,再去处理不相等的状况,若是a,b在同一个并查集中,那么显然不成立。若是不在,就能够知足。
上代码:
#include<cstdio> #include<algorithm> #include<string> #include<cstring>
#define N 1000005
using namespace std; int n; int f[N]; int g[N]; bool flag; int find(int x) { if(f[x]==x) { return f[x]; } int fx = find(f[x]); g[x] = (g[f[x]]+g[x])%2; return f[x] = fx; } struct node { int x; int y; int a; int num; int p; }nd[N+N+N]; void uion(int x,int y,int a) { int fx = find(x); int fy = find(y); if(fx!=fy) { f[fy] = fx; if(a==1) { g[fy] = (g[x]-g[y]+2)%2; }else { g[fy] = (g[x]-g[y]+2+1)%2; } } } int cmp(node a,node b) { return a.p<b.p; } void init() { memset(g,0,sizeof(g)); memset(nd,0,sizeof(nd)); flag = 0; scanf("%d",&n); for(int i = 1;i<=n;i++) { scanf("%d%d%d",&nd[i].p,&nd[i+n].p,&nd[i+n+n].a); nd[i].num = i; nd[i+n].num = i; } } void disperse() { sort(nd+1,nd+1+n+n,cmp); int cnt = 1; for(int i = 1;i<=n+n;i++) { if(!nd[nd[i].num].x) { nd[nd[i].num].x = cnt; }else { nd[nd[i].num].y = cnt; } if(nd[i+1].p!=nd[i].p) { cnt++; } } for(int i = 1;i<=n;i++) { nd[i].a = nd[i+n+n].a; } for(int i = 1;i<=cnt;i++) { f[i] = i; } } void solve() { for(int i = 1;i<=n;i++) { if(nd[i].a==1) { uion(nd[i].x,nd[i].y,nd[i].a); } } for(int i = 1;i<=n;i++) { if(nd[i].a==0) { int fx = find(nd[i].x); int fy = find(nd[i].y); if(fx==fy) { printf("NO\n"); flag = 1; return ; } } } } int main() { int t; scanf("%d",&t); while(t--) { init(); disperse(); solve(); if(flag==0) { printf("YES\n"); } } } /* 第三组数据奉上 1 9 24 234 1 2837 1 1 242 78 0 23 1 1 223 977 0 254 76 1 235 877 0 235 987 0 877 987 0 */