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");
    }
}
View Code

相关文章: