【洛谷P1955】程序自动分析【并查集】【离散】

##题目大意:
题目链接:https://www.luogu.org/problemnew/show/P1955
给出nn个变量之间的关系(等或不等),求这些活能否全部是真话。


##思路:
考虑并查集,先将读入的排序,给出相等关系的在前,不等关系的在后。那么对于所有相等的两个变量,我们将它们化为同一集合。之后对于不相等的变量,我们看看这两个变量是否在同一集合内,如果在同一集合内,说明这两个变量是相等的,所以肯定不成立;否则成立,继续往下。
但是这样由于变量的名称比较大,所以要离散之后再用并查集。


##代码:

#include <cstdio>
#include <algorithm>
using namespace std;

int t,n,x,y,len,father[200011],b[200011];

struct node{
  int x,y,z;
}a[200011];

bool cmp(node x,node y)
{
	return x.z>y.z;
}

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

int main()
{
	scanf("%d",&t);
	while (t--)
	{
		scanf("%d",&n);
		for (int i=1;i<=n;i++)
		{
			scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
			b[i]=a[i].x;
			b[i+n]=a[i].y;  //记录变量
		}
		stable_sort(b+1,b+1+n*2);  //排序
		len=unique(b+1,b+1+n*2)-b-1;  //去重,返回最后数组的长度
		for (int i=1;i<=len;i++) father[i]=i;	
		for (int i=1;i<=n;i++) 
		{
            a[i].x=lower_bound(b+1,b+len+1,a[i].x)-b-1;
            a[i].y=lower_bound(b+1,b+len+1,a[i].y)-b-1;  //离散
        }
        stable_sort(a+1,a+1+n,cmp);  //排序
        for (int i=1;i<=n;i++)
        {
        	int x=find(a[i].x),y=find(a[i].y);
        	if (a[i].z)  //相等关系
        	 if (x!=y)
        	  father[min(x,y)]=max(x,y);  //进入同一集合
        	if (!a[i].z) if (x==y)   //不成立
        	 {
        	 	printf("NO\n");
        	 	break;
        	 }
        	if (i==n) printf("YES\n");
        }
	}
}
原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998651.html