程序自動分析(BZOJ 4195)
阿新 • • 發佈:2018-10-11
led \n 同時 全部 獨立 現在 memset sort 數據規模
對於每個問題,包含若幹行:
第1行包含1個正整數n,表示該問題中需要被滿足的約束條件個數。
接下來n行,每行包括3個整數i,j,e,描述1個相等/不等的約束條件,相鄰整數之間用單個空格隔開。若e=1,則該約束條件為xi=xj;若e=0,則該約束條件為xi≠xj。
2
1 2 1
1 2 0
2
1 2 1
2 1 1
YES
在第二個問題中,約束條件為:x1=x2,x2=x1。這兩個約束條件是等價的,可以被同時滿足。
1≤n≤1000000
1≤i,j≤1000000000
Description
在實現程序自動分析的過程中,常常需要判定一些約束條件是否能被同時滿足。
考慮一個約束滿足問題的簡化版本:假設x1,x2,x3,…代表程序中出現的變量,給定n個形如xi=xj或xi≠xj的變量相等/不等的約束條件,請判定是否可以分別為每一個變量賦予恰當的值,使得上述所有約束條件同時被滿足。例如,一個問題中的約束條件為:x1=x2,x2=x3,x3=x4,x1≠x4,這些約束條件顯然是不可能同時被滿足的,因此這個問題應判定為不可被滿足。 現在給出一些約束滿足問題,請分別對它們進行判定。Input
輸入文件的第1行包含1個正整數t,表示需要判定的問題個數。註意這些問題之間是相互獨立的。
Output
輸出文件包括t行。
輸出文件的第k行輸出一個字符串“YES”或者“NO”(不包含引號,字母全部大寫),“YES”表示輸入中的第k個問題判定為可以被滿足,“NO”表示不可被滿足。Sample Input
22
1 2 1
1 2 0
2
1 2 1
2 1 1
Sample Output
NOYES
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)