AcWing 237. 程序自动分析
Luogu P1955 [NOI2015] 程序自动分析

题目描述

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

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

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

输入格式

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

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

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

输出格式

输出包括tt 行。

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

样例 #1

样例输入 #1

1
2
3
4
5
6
7
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1

样例输出 #1

1
2
NO
YES

样例 #2

样例输入 #2

1
2
3
4
5
6
7
8
9
10
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

1
2
YES
NO

提示

【样例解释1】

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

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

【样例说明2】

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

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

【数据范围】

注:实际上n106n\le 10^6

题解

并查集

AC Code

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <bits/stdc++.h>

using namespace std;

int t, n, f[1000007], book[1000007*3]; //t表示t组数据,n表示有n个操作,f[]是并查集的数字,book[]是离散化的数组

struct node {
int x, y, e;
} a[1000001];

bool cmp(node a, node b) {
return a.e > b.e;
} //将e==1的放在前面

inline void init(int kkk) {
for(int i = 1; i <= kkk; i++)
f[i] = i;
}

int get(int x) {
if(x == f[x])
return x;
return f[x] = get(f[x]);
}

int main() {
cin >> t;
while(t--) {
int tot = -1;
memset(book, 0, sizeof(book));
memset(a, 0, sizeof(a));
memset(f, 0, sizeof(f));
int flag = 1;
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y >> a[i].e;
book[++tot] = a[i].x;
book[++tot] = a[i].y;
}
sort(book, book + tot);
int reu = unique(book, book + tot) - book; //去重
for(int i = 1; i <= n; ++i) {
a[i].x = lower_bound(book, book + reu, a[i].x) - book;
a[i].y = lower_bound(book, book + reu, a[i].y) - book;
}
init(reu);
sort(a + 1, a + n + 1, cmp); //按e排序
for(int i = 1; i <= n; i++) {
int r1 = get(a[i].x);
int r2 = get(a[i].y);
if(a[i].e) {
f[r1] = r2;
} else if(r1 == r2) {
cout << "NO" << endl;
flag = 0;
break;
}
}
if(flag)
cout << "YES" << endl;
}
return 0;
}