【NOI 2015】程序自动分析 并查集与离散化处理
题目描述
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足。
考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或xi≠xj的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为:x1=x2,x2=x3,x3=x4,x1≠x4,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。
现在给出一些约束满足问题,请分别对它们进行判定。
输入
输入文件的第1行包含1个正整数t,表示需要判定的问题个数。注意这些问题之间是相互独立的。
对于每个问题,包含若干行:
第1行包含1个正整数n,表示该问题中需要被满足的约束条件个数。
接下来n行,每行包括3个整数i,j,e,描述1个相等/不等的约束条件,相邻整数之间用单个空格隔开。若e=1,则该约束条件为xi=xj;若e=0,则该约束条件为xi≠xj。
输出
输出文件包括t行。
输出文件的第k行输出一个字符串“YES”或者“NO”(不包含引号,字母全部大写),“YES”表示输入中的第k个问题判定为可以被满足,“NO”表示不可被满足。
测试输入
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
测试输出
NO
YES
提示
在第一个问题中,约束条件为:x1=x2,x1≠x2。这两个约束条件互相矛盾,因此不可被同时满足。
在第二个问题中,约束条件为:x1=x2,x2=x1。这两个约束条件是等价的,可以被同时满足。
1≤n≤1000000
1≤i,j≤1000000000
题目分析
对于本题,目的是判断程序能否满足所有的输入,因为只有相同和不同两种关系,那么我们可以先处理所有的相同的关系,将相同的数对用并查集维护成一个个不相交集合或者相交集合,而后再处理不同的数对,一旦不同的数对在同一个集合中则发生矛盾,输出NO即可,遍历完所有的不同数对发现确实都属于不同的集合则输出YES,本题需要注意的是输入数字较大,需要用离散化进行处理,直接开数组是不行的
注意点
- 关于并查集的建立,本题由于数据量很大,所以需要用到路径压缩,注释的部分是不采用路径压缩时的代码,路径压缩目的能使一个集合在与另一个集合合并前是以一棵深度只有1的树,这样减少了部分查询的消耗(数据量大的时候更为明显)
int find(int x){
if(p[x] == x) return x;
else{
p[x] = find(p[x]);
}
return p[x];
// while(p[x] != x){
// x = p[x];
// }
// return x;
}
- 关于C++ STL中的unique()函数,它的作用是对一个已经排序完成的数组,实现“合并”相邻的相同数字,为什么合并要带引号呢?事实上,合并后的数组长度未发生变化,它合并的过程是不断把后面的元素覆盖前面重复元素(具体就不作讲解了),在对数组执行unique操作时,一般接受两个参数,数组的首地址和尾地址,而它的返回值是完成查重后的数组的有序位最后一个+1的引用,就是说数组1,1,2,2,4,5,5,6通过unique(a, a+8)之后数组就变成了1,2,4,5,6,5,5,6只有前5个是有序的,且int t = unique(a, a+8)存放的是a[5]的引用,所以如果想得到具体是第几个那么我们一般写成int t = unique(a, a + 8) - a;那么t自然而然就是5,下面是代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int main(){
int a[] = {1, 1, 2, 2, 4, 5, 5, 6};
int t = unique(a, a + 8) - a;
cout<<t<<endl;
cout<<a[t]<<endl;
for(int i = 0; i <= 7; i++){
cout<<a[i]<<endl;
}
return 0;
}
- 关于lower_bound()函数的使用,这是一个高效的方法用二分查找数组中第一次出现某个数的引用,它接收三个参数,数组首地址,数组尾地址,需要查询的数的值,一般我们将查询出的结果减去数组名,则得到一个数组中下标为i的位置是第一次出现查找的number的位置
i = lower_bound(a + 1, a + n + 1, number) - a;
- 离散化:因为数据量i,j很大,而最多有1000000对输入,显然最多有2000000个不同的数字,我们可以构建一个2000000大的数组存放这所有的输入的i,j(尽管它们本身可能大大超出2000000但放在这个数组里却没有任何问题)
本题代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int N = 1000005;
int p[N<<1];
int m[N<<1];
int x[N];
int y[N];
int type[N];
int n, cnt, num;
struct Node{ //结构体是用于存放那些不同的数对的i j的第一次在数组中出现的位置
int x, y;
}k[N<<1];
void merge(){ //合并重复元素,实际上是覆盖操作,数组长度未发生变化,temp存放最后一个有序位置的索引(因为-m-1)
sort(m + 1, m + num + 1);
int temp = unique(m + 1, m + num + 1) - m - 1;
for(int i = 1; i <= n; i++){
x[i] = lower_bound(m + 1, m + temp + 1, x[i]) - m; //lowerbound()前两个参数的闭区间和开区间
y[i] = lower_bound(m + 1, m + temp + 1, y[i]) - m; //执行完成后x[i]存放m数组中第一次出现x[i]的位置
}
}
int find(int x){
if(p[x] == x) return x;
else{
p[x] = find(p[x]);
}
return p[x];
// while(p[x] != x){
// x = p[x];
// }
// return x;
}
void Union(int x, int y){
int fx = find(x);
int fy = find(y);
if(fx != fy) p[fy] = fx;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
cnt = 0;
num = 0;
for(int i = 1; i <= n; i++){ //对输入的n组输入进行2*n的离散化处理
scanf("%d%d%d", &x[i], &y[i], &type[i]);
m[++num] = x[i];
m[++num] = y[i];
}
for(int i = 1; i <= num; i++) p[i] = i; //p数组存放根
merge();
for(int i = 1; i <= n; i++){
if(type[i] == 1){
Union(x[i], y[i]); //type == 1时 将根合并同时路径压缩,这里要注意,x[i] y[i]
}else{ //存放的是第一次出现位置,只有这样才能在2000000空间中查询1000000000大的数
k[++cnt].x = x[i]; //k结构体数组存放type == 0时数对x[i],y[i]第一次在数组m中出现的位置
k[cnt].y = y[i];
}
}
int flag = 0;
for(int i = 1; i <= cnt; i++){
int fx = find(k[i].x);
int fy = find(k[i].y);
if(fx == fy){ //如果根相同 则说明相等 矛盾
flag = 1;
printf("NO\n");
break;
}
}
if(flag == 0){
printf("YES\n");
}
}
return 0;
}
【NOI 2015】程序自动分析 并查集与离散化处理的更多相关文章
- 洛谷P1955 [NOI2015] 程序自动分析 [并查集,离散化]
题目传送门 题目描述 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量,给定n个形如xi=xj或x ...
- BZOJ-4195 NOI2015Day1T1 程序自动分析 并查集+离散化
总的来说,这道题水的有点莫名奇妙,不过还好一次轻松A 4195: [Noi2015]程序自动分析 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 836 ...
- [BZOJ4195] [NOI2015] 程序自动分析 (并查集)
Description 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xj或x ...
- BZOJ 4195: [Noi2015]程序自动分析 并查集+离散化
LUOGU 1955BZOJ 4195 题目描述 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量 ...
- 【BZOJ4195】[Noi2015]程序自动分析 并查集
[BZOJ4195][Noi2015]程序自动分析 Description 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3 ...
- BZOJ 4195: [Noi2015]程序自动分析 [并查集 离散化 | 种类并查集WA]
题意: 给出若干相等和不等关系,判断是否可行 woc NOI考这么傻逼的题飞快打了一个种类并查集交上了然后爆零... 发现相等和不等看错了异或一下再叫woc90分 然后发现md$a \neq b, a ...
- NOI2015程序自动分析 并查集
有10^9个点,每次给出两个点的关系:权相等或不等,问最后能不能成立 感觉一开始在撕烤一个动态的问题,,,想写一个带权的并查集 结果发现静态询问,那就sb乱搞,懒得手写离散就直接map(卧槽好多细节忘 ...
- bzoj4195 [Noi2015]程序自动分析——并查集
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4195 突然在这道大水题上WA了半天... 思路很简单,离线处理询问,先把 = 的都加到并查集 ...
- [Bzoj4195] [NOI2015] 程序自动分析 [并查集,哈希,map] 题解
用并查集+离散化,注意:并查集数组大小不是n而是n*2 #include <iostream> #include <algorithm> #include <cstdio ...
随机推荐
- Fabric1.4源码解析:Peer节点加入通道
又开始新的阅读了,这次看的是Peer节点加入通道的过程.其实每次看源码都会有好多没有看懂的地方,不过相信只要坚持下去,保持记录,还是有很多收获的. 对于Peer节点加入通道这一 ...
- Codeforces Round #563 (Div. 2)C
C. Ehab and a Special Coloring Problem 题目链接:http://codeforces.com/contest/1174/problem/C 题目 You're g ...
- selenium3+python3自动化测试学习之网页元素定位
selenium基础实战之定位网页元素技巧 selenium定位网页元素 find_element_by_id,find_element_by_name,find_element_by_class_n ...
- Analysis of requirement specification of parking management system
Analysis of requirement specification of parking management system PURPOSE OF THE SYSTEM The parking ...
- 阿里云服务器纯净版centos7.4 LNMP安装
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE /* Style Definitions */ table.MsoNormalTable ...
- top命令输出详解
前言 Linux下的top命令我相信大家都用过,自从我接触Linux以来就一直用top查看进程的CPU和MEM排行榜.但是top命令的其他输出结果我都没有了解,这些指标都代表什么呢,什么情况下需要关注 ...
- Oracle数据库备份---导出与导入
利用windows的cmd命令备份导出数据(也可以连接上sqlplus进行操作)--导出--将数据库orcl完全导出 exp system/oracle@orcl file=c:\oracle_bak ...
- FTP工具便携版 FileZilla 3.38.0
FileZilla 客户端是一个快速可靠的.跨平台的FTP,FTPS和SFTP客户端.具有图形用户界面(GUI)和很多有用的特性.由NoCmd提供的 FileZilla Client 中文便携版,具有 ...
- maven打包报错问题解析
1. 场景描述 Failed to execute goal org.apache.maven.plugins:maven-clean-plugin:3.1.0:clean (default-clea ...
- 【UR #7】水题走四方 题解
链接:http://uoj.ac/problem/84 20分算法:萌萌的小爆搜,别搜进环里就行. 50分:我们考虑一下最优决策是什么样的.看似很显然的一点就是我们先让本体在原地不动,让分身去遍历子树 ...