【并查集+离散化】BZOJ4195- [Noi2015]程序自动分析
【题目大意】
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。
考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。
现在给出一些约束满足问题,请分别对它们进行判定。
【思路】
智障啊!!
完全是一道超级水的并查集,我居然以为是和关押罪犯一样分为两类的……
简单来说,先把放一起的处理掉,然后再判断不能放在一起的,如果它们在一个并查集里着返回“No”...
忘掉unique怎么写了…………按照自己的想法胡乱地弄了一下离散化……胡乱地……
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 const int MAXN=2000000+500; 8 struct node 9 { 10 int num; 11 int oripos; 12 int ab;//0a1b 13 bool operator < (const node &x) const 14 { 15 return num<x.num; 16 } 17 }que[MAXN]; 18 int h[MAXN],u[MAXN]; 19 int n,a[MAXN],b[MAXN],e[MAXN]; 20 21 void union_set(int a,int b) 22 { 23 if (h[a]>=h[b]) 24 { 25 u[b]=a; 26 if (h[a]==h[b]) h[a]++; 27 } 28 else u[a]=b; 29 } 30 31 int find(int x) 32 { 33 int r=x; 34 while (u[r]!=r) r=u[r]; 35 int p=x; 36 while (u[p]!=p) 37 { 38 int tmp=u[p]; 39 u[p]=r; 40 p=tmp; 41 } 42 return r; 43 } 44 45 46 void init() 47 { 48 scanf("%d",&n); 49 int qlen=-1; 50 for (int i=0;i<n;i++) 51 { 52 scanf("%d%d%d",&a[i],&b[i],&e[i]); 53 que[++qlen].num=a[i]; 54 que[qlen].oripos=i; 55 que[qlen].ab=0; 56 que[++qlen].num=b[i]; 57 que[qlen].oripos=i; 58 que[qlen].ab=1; 59 } 60 sort(que,que+2*n); 61 int j=0; 62 for (int i=0;i<2*n;i++) 63 { 64 if (i!=0 && que[i].num!=que[i-1].num) j++; 65 if (que[i].ab==0) a[que[i].oripos]=j; 66 else b[que[i].oripos]=j; 67 } 68 memset(h,0,sizeof(h)); 69 for (int i=0;i<=2*(n+2);i++) u[i]=i; 70 } 71 72 int judge() 73 { 74 for (int i=0;i<n;i++) 75 if (e[i]) 76 { 77 union_set(find(a[i]),find(b[i])); 78 } 79 for (int i=0;i<n;i++) 80 if (!e[i]) 81 { 82 int fa=find(a[i]),fb=find(b[i]); 83 if (fa==fb) return 0; 84 } 85 return 1; 86 } 87 88 int main() 89 { 90 int T; 91 scanf("%d",&T); 92 while (T--) 93 { 94 init(); 95 int j=judge(); 96 if (j) cout<<"YES"<<endl;else cout<<"NO"<<endl; 97 } 98 return 0; 99 }