P1955 [NOI2015] 程序自动分析

题面

在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。

考虑一个约束满足问题的简化版本:假设 \(x_1,x_2,x_3,\cdots\) 代表程序中出现的变量,给定 \(n\) 个形如 \(x_i=x_j\)\(x_i\neq x_j\) 的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:\(x_1=x_2,x_2=x_3,x_3=x_4,x_4\neq x_1\),这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。

现在给出一些约束满足问题,请分别对它们进行判定。

【数据范围】

【数据范围】

思路

可以用并查集维护。

如果相等,那么合并。如果不等,检查是否在一个集合中,如果在就是 NO, 否则就是 YES

至于值域问题,可以考虑以下方案:

  • 离散化
  • 使用映射数据结构(如 std::mapstd::unordered_map__gnu_pbds::gp_hash_table 等)。

这里使用第二种。经过实验,只有 std::unordered_map 能过。其他都是 \(90\) 分(开了 \(\text{O2}\) )。

#include <bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
//using namespace __gnu_pbds;

const int SIZE = 1e6+5;
int t,T;
struct query{
	int i,j,e;
} querys[SIZE];

unordered_map<int,int> fa;

namespace IO{
	const int SIZE=1<<21;
	static char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=oS+SIZE-1;
    int qr;
    char qu[55],c;
    bool f;
	#define getchar() (IO::iS==IO::iT?(IO::iT=(IO::iS=IO::ibuf)+fread(IO::ibuf,1,IO::SIZE,stdin),(IO::iS==IO::iT?EOF:*IO::iS++)):*IO::iS++)
	#define putchar(x) *IO::oS++=x,IO::oS==IO::oT?flush():0
	#define flush() fwrite(IO::obuf,1,IO::oS-IO::obuf,stdout),IO::oS=IO::obuf
	#define puts(x) IO::Puts(x)
	template<typename T>
    inline void read(T&x){
    	for(f=1,c=getchar();c<48||c>57;c=getchar())f^=c=='-';
    	for(x=0;c<=57&&c>=48;c=getchar()) x=(x<<1)+(x<<3)+(c&15); 
    	x=f?x:-x;
    }
    template<typename T>
    inline void write(T x){
        if(!x) putchar(48); if(x<0) putchar('-'),x=-x;
        while(x) qu[++qr]=x%10^48,x/=10;
        while(qr) putchar(qu[qr--]);
    }
    inline void Puts(const char*s){
    	for(int i=0;s[i];i++)
			putchar(s[i]);
		putchar('\n');
	}
	struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}
using IO::read;
using IO::write;
int find(int x){
	if(fa[x]==x)return x;
	else return fa[x]=find(fa[x]);
}

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

bool same(int x,int y){
	return find(x)==find(y);
}

void solve(){
	read(t);
	for(int i=1;i<=t;i++){
		query &nq=querys[i];
		read(nq.i);read(nq.j);read(nq.e);
	}
	for(int i=1;i<=t;i++){
		query &nq=querys[i];
		fa[nq.i]=nq.i;
		fa[nq.j]=nq.j;
	}
	for(int i=1;i<=t;i++){
		query &nq=querys[i];
		if(nq.e==1){
			merge(nq.i,nq.j);
		}
	}
	for(int i=1;i<=t;i++){
		query &nq=querys[i];
		if(nq.e==0){
			if(same(nq.i,nq.j)){
				putchar('N');putchar('O');putchar('\n');
				return;
			}
		}
	}
	putchar('Y');putchar('E');putchar('S');putchar('\n');
}

int main(){
   read(T);
	while(T--){
		solve();
	}
	return 0;
}

建议使用 C++14 (GCC 9) O2

AC 记录

posted @ 2022-03-17 13:06  蒟蒻xiezheyuan  阅读(61)  评论(0编辑  收藏  举报