[NOI2015]程序自动分析

洛咕

题意:考虑一个约束满足问题的简化版本:假设(x1,x2,x3...)代表程序中出现的变量,给定(n(n<=1e5))个形如(xi=xj)(xi≠xj)的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:(x1=x2,x2=x3,x3=x4,x4≠x1),这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足.现在给出一些约束满足问题,请分别对它们进行判定.(x_i<=1e9.)

分析:相等的条件是具有传递性的,例如(x_1=x_2,x_2=x_3),则我们可以推出(x_1=x_3),而不相等的条件是不具有传递性的.因为并查集擅长解决具有传递性关系的问题,所以我们先只考虑相等的条件,对于每个相等的条件(x_i=x_j),用并查集维护(如果不在同一个集合,就合并到同一个集合中,所以同一个集合内的数都相等).

然后再扫描所有的不等条件,(xi≠xj),如果在同一个集合,则产生矛盾.

因为(x_i<=1e9),不好用数组下标维护,所以先要对它们进行离散化.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=2e5+5;
int b[N],fa[N];
struct ppx{int x,y,z;}a[N];
inline int get(int x){
	if(x==fa[x])return x;
	return fa[x]=get(fa[x]);
}
int main(){
	int T=read();
	while(T--){
		int n=read(),tot=0,bj=1;
		for(int i=1;i<=n;++i){
			a[i].x=read();a[i].y=read();a[i].z=read();
			b[++tot]=a[i].x;b[++tot]=a[i].y;
		}
		sort(b+1,b+tot+1);int sum=unique(b+1,b+tot+1)-b-1;
		for(int i=1;i<=n;++i){
			a[i].x=lower_bound(b+1,b+sum+1,a[i].x)-b;
			a[i].y=lower_bound(b+1,b+sum+1,a[i].y)-b;
		}
		for(int i=1;i<=sum;++i)fa[i]=i;
		for(int i=1;i<=n;++i){
			if(a[i].z==1){
				int x=get(a[i].x),y=get(a[i].y);
				if(x!=y)fa[x]=y;
			}
		}
		for(int i=1;i<=n;++i){
			if(!a[i].z){
				int x=get(a[i].x),y=get(a[i].y);
				if(x==y){puts("NO");bj=0;break;}
			}
		}
		if(bj)puts("YES");
	}
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/11613096.html