4195: [Noi2015]程序自动分析
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 3470 Solved: 1626
[Submit][Status][Discuss]
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。
1≤n≤1000000
1≤i,j≤1000000000
题解:
这题可以离线,并且是对整体进行询问,直接离线所有判断,然后并查集合并所有等号,对不等号一一判断即可;
想说的是这个题的在线版本(ORZ wwwwodddd)
依旧用并查集,但是用set对每个并查集维护一个敌人集合,然后合并两个集合的时候启发式合并set即可,需要离散化;(两份代码都放了OVO)
复杂度O(nlogn)
1 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int N=2000010; 5 int T,n,tot,tx[N],ty[N],cnt,fa[N]; 6 map<int,int>mp; 7 int get(int x){ 8 if(!mp[x])mp[x]=++tot,fa[tot]=tot; 9 return mp[x]; 10 } 11 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 12 int main(){ 13 // freopen("bzoj4195.in","r",stdin); 14 // freopen("bzoj4195.out","w",stdout); 15 scanf("%d",&T); 16 while(T--){ 17 scanf("%d",&n); 18 tot=cnt=0;mp.clear(); 19 for(int i=1,x,y,e;i<=n;i++){ 20 scanf("%d%d%d",&x,&y,&e); 21 x=get(x);y=get(y); 22 if(e){ 23 int fx=find(x),fy=find(y); 24 if(fx!=fy)fa[fx]=fy; 25 }else tx[++cnt]=x,ty[cnt]=y; 26 } 27 int fg=0; 28 for(int i=1;i<=cnt;i++)if(find(tx[i])==find(ty[i])){fg=1;break;} 29 puts(fg?"NO":"YES"); 30 } 31 return 0; 32 }