洛谷1955 程序自动分析

传送门

并查集。

一眼傻逼题,直接离线把一样的合并按不一样的判断即可。

然后30。

发现要离散。

然后50。

空间要开两倍。

//Twenty
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int mod=1e9+7;
int T,n,sza,szb,a[maxn*2][2],b[maxn*2][2],fa[maxn*2],ls[maxn*2],sz;

void read(int &ret) {
    int f=1; ret=0; char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0'; ret*=f;
}

int find(int x) {
    return x==fa[x]?x:fa[x]=find(fa[x]);
}

int hs(int x) {
    return lower_bound(ls+1,ls+sz+1,x)-ls;
}

int ck() {
	sort(ls+1,ls+sz+1);
	int tpsz=unique(ls+1,ls+sz+1)-(ls+1); sz=tpsz;
    for(int i=1;i<=2*n;i++) fa[i]=i;
    for(int i=1;i<=sza;i++) {
	    int x=hs(a[i][0]),y=hs(a[i][1]);
	    int u=find(x),v=find(y);
	    if(u==v) continue;
	    fa[u]=v;
	}
	for(int i=1;i<=szb;i++) {
	    int x=hs(b[i][0]),y=hs(b[i][1]);
	    int u=find(x),v=find(y);
	    if(u==v) return 0;
	}
	return 1;
}

void init() {
    read(T);
    while(T--) {
	    int x,y,z;
	    sza=0; szb=0; sz=0;
	    read(n);
	    for(int j=1;j<=n;j++) {
	        read(x); read(y); read(z);
	        ls[++sz]=x;
	        ls[++sz]=y;
	        if(z==1) {
		        a[++sza][0]=x;
		        a[sza][1]=y;
	    	}
		    else {
		        b[++szb][0]=x;
		        b[szb][1]=y;
		    }
		}
		if(ck()) printf("YES\n");
		else  printf("NO\n");
	}
}

int main()
{
	init();
	return 0;
}

  

posted @ 2017-10-24 21:05  啊宸  阅读(188)  评论(0编辑  收藏  举报