1. 程式人生 > >程序自動分析(BZOJ 4195)

程序自動分析(BZOJ 4195)

led \n 同時 全部 獨立 現在 memset sort 數據規模

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

Sample Output

NO
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; }

程序自動分析(BZOJ 4195)