NOI2015 - 程序自动分析

【LuoguP1955】【BZOJ4195】【NOI2015】程序自动分析
题目链接1: https://www.luogu.org/problemnew/show/P1955
题目链接2: https://www.lydsy.com/JudgeOnline/problem.php?id=4195

引言

最近变得越来越颓废. 介于好长时间没更新博客, 强行水一篇题解.

这道题没看题解15分钟就A了, 真的有点水了…

分析

题意大概就是有 N 个关系, 每个代表X1 = X2 或者 X1 ≠ X2, 求出这些关系能不能成立.

很容易就想到并查集, 先将相等的X合并, 然后判断不等关系的两个变量在不在一个并查集里就行了.那么就只需要排下序, 先进行合并操作再去判断.

判断不等关系过程中发现X1和X2在同一个并查集里, 那直接输出NO就行了.

然而X的下标可能会很大. 所以考虑离散化, 那么肯定直接上map.

输入的时候就离散化, 然后排个序, 打完合并和查询就AC了.

不过map常数巨大, 需要开O2稳过.

代码

评测详情(O2):
Accepted 100
用时: 1623ms / 内存: 11960KB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <stdio.h>
#include <map>
#include <algorithm>
using namespace std;
int t, n, f[200001], mptr, cnt, flag;
struct date {
int x, y, d;
bool operator<(const date &d2) const {
return d > d2.d;
}
} dat[100001];
int query(int x) {
if(f[x] == x) return x;
return f[x]= query(f[x]);
}
map< int, int > m;
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
mptr= cnt= flag= 0;
m.clear();
for(int i= 1; i <= n; i++) {
scanf("%d%d%d", &dat[i].x, &dat[i].y, &dat[i].d);
if(!m.count(dat[i].x)) m[dat[i].x]= ++mptr;
if(!m.count(dat[i].y)) m[dat[i].y]= ++mptr;
dat[i].x= m[dat[i].x], dat[i].y= m[dat[i].y];
cnt+= dat[i].d;
}
sort(dat + 1, dat + n + 1);
for(int i= 1; i <= mptr; i++) f[i]= i;
for(int i= 1; i <= cnt; i++) {
int fx= query(dat[i].x);
f[query(dat[i].y)]= fx;
}
for(int i= cnt + 1; i <= n; i++) {
if(query(dat[i].x) == query(dat[i].y)) {
printf("NO\n");
flag= 1;
break;
}
}
if(!flag) printf("YES\n");
}
return 0;
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×