ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

P1955 [NOI2015] 程序自动分析

2022-07-25 09:03:40  阅读:161  来源: 互联网

标签:约束条件 P1955 int 样例 NOI2015 满足 自动 判定 neq


Luogu 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\),这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。

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

输入格式

输入的第一行包含一个正整数 \(t\),表示需要判定的问题个数。注意这些问题之间是相互独立的。

对于每个问题,包含若干行:

第一行包含一个正整数 \(n\),表示该问题中需要被满足的约束条件个数。接下来 \(n\) 行,每行包括三个整数 \(i,j,e\),描述一个相等/不等的约束条件,相邻整数之间用单个空格隔开。若 \(e=1\),则该约束条件为 \(x_i=x_j\)。若\(e=0\),则该约束条件为 \(x_i\neq x_j\)。

输出格式

输出包括 \(t\) 行。

输出文件的第 \(k\) 行输出一个字符串 YES 或者 NO(字母全部大写),YES 表示输入中的第 \(k\) 个问题判定为可以被满足,NO 表示不可被满足。

样例 #1

样例输入 #1
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
样例输出 #1
NO
YES

样例 #2

样例输入 #2
2
3
1 2 1
2 3 1
3 1 1
4
1 2 1
2 3 1
3 4 1
1 4 0
样例输出 #2
YES
NO

提示

【样例解释1】

在第一个问题中,约束条件为:\(x_1=x_2,x_1\neq x_2\)。这两个约束条件互相矛盾,因此不可被同时满足。

在第二个问题中,约束条件为:\(x_1=x_2,x_1 = x_2\)。这两个约束条件是等价的,可以被同时满足。

【样例说明2】

在第一个问题中,约束条件有三个:\(x_1=x_2,x_2= x_3,x_3=x_1\)。只需赋值使得 \(x_1=x_2=x_3\),即可同时满足所有的约束条件。

在第二个问题中,约束条件有四个:\(x_1=x_2,x_2= x_3,x_3=x_4,x_4\neq x_1\)。由前三个约束条件可以推出 \(x_1=x_2=x_3=x_4\),然而最后一个约束条件却要求 \(x_1\neq x_4\),因此不可被满足。

【数据范围】

注:实际上 \(n\le 10^6\) 。

Solution

看到题目,可以将等于的条件看作边,那么所有的等于条件就是将一些点连在一起形成许多连通块。并且可以知道在等于条件连边的情况下是不可能出现与之前条件矛盾的情况,那么就可以将所有的等于条件提前至所有不等于条件之前来进行处理。

现在来看不等号的条件怎么处理,首先可以得出不等号的条件不会影响之后的任何不等号。因此将不等号当作不对条件产生影响的询问进行处理。因为我们将等于条件提前了,并且利用这些条件建了一个不一定全部联通的图,那么不等于条件就可以转化为询问不等号两边的数在图上是否是联通的。这样就将原题转化为了一个给出图判定连通性的问题。对于判定图的连通性的问题直接用带路径压缩的并查集就可以了。

另外需要注意到题目中 \(1\le i,j \le 1\times 10^9\) 这一条件,因为 \(1e9\) 的数据量没法直接用数组存下,而注意到 \(n\) 的范围是 \(1e5\) ,所以可以采用离散化对原数列进行处理,这样就将值域控制在了 \(1e5\) 这一数量级。

这样这道 \(\text{NOI}\) 的题就被我们切掉了。

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
template<typename T> void read(T &k)
{
	k=0;T flag=1;char b=getchar();
	while (!isdigit(b)) {flag=(b=='-')?-1:1;b=getchar();}
	while (isdigit(b)) {k=k*10+b-48;b=getchar();}
	k*=flag;
}
const int _SIZE=1e6;
int T,n;
int fa[_SIZE+5],order[(_SIZE<<1)+5];
struct EQUAL{
	int x,y,e;
	bool operator<(const EQUAL &a)const{
		return e>a.e;
	}
}a[_SIZE+5];
void init()
{
	mem(fa,0);mem(order,0);
}
int find(int x)
{
	if (x!=fa[x]) return fa[x]=find(fa[x]);
	return x;
}
int main()
{
	read(T);
	while (T--)
	{
		read(n);
		for (int i=1;i<=n;i++)
		{
			read(a[i].x);read(a[i].y);
			read(a[i].e);
			order[(i<<1)-1]=a[i].x,order[(i<<1)]=a[i].y;
		}
		sort(order+1,order+(n<<1)+1);
		int tot=unique(order+1,order+(n<<1)+1)-order-1;
		for (int i=1;i<=n;i++)
		{
			a[i].x=lower_bound(order+1,order+tot+1,a[i].x)-order;
			a[i].y=lower_bound(order+1,order+tot+1,a[i].y)-order;
			//printf("%d %d\n",a[i].x,a[i].y);
		}
		sort(a+1,a+n+1);
		for (int i=1;i<=tot;i++) fa[i]=i;
		bool flag=0;
		for (int i=1;i<=n;i++)
		{
			int f1=find(a[i].x);
			int f2=find(a[i].y);
			if (a[i].e) fa[f1]=f2;
			else if (f1==f2) {flag=1;break;}
			//printf("%d %d\n",f1,f2);
		}
		if (flag) printf("NO\n");
		else printf("YES\n");
	}
	return 0;
}

标签:约束条件,P1955,int,样例,NOI2015,满足,自动,判定,neq
来源: https://www.cnblogs.com/hanx16msgr/p/16516213.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有