NOI2015D1T1
题目大意:$T$ 组数据。在一个程序中有无数个变量 $x_i$。现在有 $n$ 条限制,形如 $x_i=x_j$ 或者 $x_i\ne x_j$。(对于每个限制 $i,j$ 给定)问是否存在一种合法的赋值方案满足所有限制。
$1\le T\le 10,1\le n\le 10^5,1\le i,j\le 10^9$。
普及难度。先把所有编号离散化,然后对于每个相等的限制,把这两个变量塞到一个集合里(并查集)。最后对于每个不等的限制,判断两个变量是否在一个集合里。
时间复杂度 $O(Tn\log n)$。
#include<bits/stdc++.h> using namespace std; int t,n,u[100010],v[100010],op[100010],tmp[200020],fa[200020]; int getfa(int x){ return fa[x]==x?x:fa[x]=getfa(fa[x]); } void comb(int u,int v){ int fu=getfa(u),fv=getfa(v); if(fu!=fv) fa[fu]=fv; } bool same(int u,int v){ int fu=getfa(u),fv=getfa(v); return fu==fv; } int main(){ scanf("%d",&t); while(t--){ memset(u,0,sizeof(u)); memset(v,0,sizeof(v)); memset(op,0,sizeof(op)); memset(tmp,0,sizeof(tmp)); scanf("%d",&n); for(int i=1;i<=2*n;i++) fa[i]=i; for(int i=1;i<=n;i++){ scanf("%d%d%d",u+i,v+i,op+i); tmp[i*2-1]=u[i]; tmp[i*2]=v[i]; } sort(tmp+1,tmp+2*n+1); unique(tmp+1,tmp+2*n+1); bool flag=true; for(int i=1;i<=n;i++){ u[i]=lower_bound(tmp+1,tmp+2*n+1,u[i])-tmp; v[i]=lower_bound(tmp+1,tmp+2*n+1,v[i])-tmp; } for(int i=1;i<=n;i++) if(op[i]==1) comb(u[i],v[i]); for(int i=1;i<=n;i++) if(op[i]==0) if(same(u[i],v[i])){ flag=false;break; } if(flag) printf("YES\n"); else printf("NO\n"); } }