【NOI2015T1】程序自动分析-并查集+离散化

测试地址:程序自动分析

做法:这个题目一看就很并查集是不是,先把相等的元素并成一个集合,然后再判断不等的条件,如果两个元素在同一个集合,直接输出NO,检查完后没有冲突的就输出YES。然而还有一点,元素的标号本身达到了10^9,直接用并查集存不下这么多,然而条件只有10^6个,也就是说最多存在2*10^6个有效元素,因此把所有在条件中出现过的元素标号排个序,然后离散化,就可以用并查集求解了。

以下是本人代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct forsort{int val,pos;} f[2000010];
int T,n,tot,op[1000010],p[1000010][2],fa[2000010];

bool cmp(forsort a,forsort b)
{
  return a.val<b.val;
}

int find(int x)
{
  int r=x,i=x,j;
  while(fa[r]!=r) r=fa[r];
  while(i!=r) {j=fa[i];fa[i]=r;i=j;}
  return r;
}

void merge(int x,int y)
{
  int fx=find(x),fy=find(y);
  fa[fx]=fy;
}

int main()
{
  scanf("%d",&T);
  while(T--)
  {
    scanf("%d",&n);
	for(int i=1,a,b;i<=n;i++)
	{
	  scanf("%d%d%d",&a,&b,&op[i]);
	  f[(i<<1)-1].val=a,f[i<<1].val=b;
	  f[(i<<1)-1].pos=f[i<<1].pos=i;
	}
	
	sort(f+1,f+(n<<1)+1,cmp);
	memset(p,0,sizeof(p));
	tot=0;
	for(int i=1;i<=n<<1;i++)
	{
	  if (i==1||(i>1&&f[i].val!=f[i-1].val)) tot++;
	  if (!p[f[i].pos][0]) p[f[i].pos][0]=tot;
	  else p[f[i].pos][1]=tot;
	}
	
	for(int i=1;i<=tot;i++)
	  fa[i]=i;
	for(int i=1;i<=n;i++)
	  if (op[i]) merge(p[i][0],p[i][1]); 
	bool flag=1;
	for(int i=1;i<=n;i++)
	  if (!op[i])
	  {
	    if (find(p[i][0])==find(p[i][1])) {printf("NO\n");flag=0;break;}
	  }
	if (flag) printf("YES\n");
  }
  
  return 0;
}


posted @ 2017-03-13 09:48  Maxwei_wzj  阅读(111)  评论(0编辑  收藏  举报