【NOI 2015】程序自动分析

时间:2023-01-26 18:57:37

【问题描述】

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

考虑一个约束满足问题的简化版本:假设 x 1 , x 2 , x 3 , ⋯ 代表程序中出现的变量,给定 n 个形如 x i = x j 或 x i ≠ x j 的变量相等/不等的约束条件,请判定是否可以分别为每一个变量赋予恰当的值,使得上述所有约束条件同时被满足。例如,一个问题中的约束条件为: x 1 = x 2 , x 2 = x 3 , x 3 = x 4 , x 1 ≠ x 4 ,这些约束条件显然是不可能同时被满足的,因此这个问题应判定为不可被满足。

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

【输入格式】

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

对于每个问题,包含若干行:第 1 行包含 1 个正整数 n(n<=100000) ,表示该问题中需要被满足的约束条件个数。

接下来 n 行,每行包括 3 个整数 i, j, e(i、j<=1000000000,0<=e<=1),描述 1 个相等/不等的约束条件,相邻整数之间用单个空格隔开。若 e = 1 ,则该约束条件为 x i = x j ;若 e = 0 ,则该约束条件为 x i ≠ x j ;

【输出格式】

输出t 行,第 k 行输出一个字符串“YES”或者“NO”(不包含引号,字母全部大写),“YES”表示输入中的第 k 个问题判定为可以被满足,“NO”表示不可被满足。

 

分析:

先把e=1的用并查集合并,再判断一下e=0的是否在一个集合。i、j需要离散化。

 

代码:

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 int t, n, fa[200010];
 5 int tn[200010], num[200010], cnt, tot;
 6 int u[100010], v[100010], w[100010];
 7 int a, b, c;
 8 
 9 int yl(int x)
10 {
11     return fa[x] == x ? x : fa[x] = yl(fa[x]);
12 }
13 
14 int low(int key)
15 {
16     int left = 1, right = cnt, mid;
17     while (left + 3 < right)
18     {
19         mid = left + right >> 1;
20         if (num[mid] == key) return mid;
21         if (num[mid] < key) left = mid;
22         else right = mid;
23     }
24     for ( ; left <= right; left++)
25         if (num[left] == key)
26             return left;
27     return -1;
28 }
29 
30 int main()
31 {
32     scanf("%d", &t);
33     while (t--)
34     {
35         scanf("%d", &n);
36         tot = cnt = tn[0] = 0;
37         for (int i = 1; i <= n; i++)
38         {
39             scanf("%d%d%d", &u[i], &v[i], &w[i]);
40             tn[++tot] = u[i];
41             tn[++tot] = v[i];
42         }
43         std::sort(tn + 1, tn + tot + 1);
44         for (int i = 1; i <= tot; i++)
45         {
46             fa[i] = i;
47             if (tn[i - 1] != tn[i])
48                 num[++cnt] = tn[i];
49         }
50         for (int i = 1; i <= n; i++)
51         {
52             u[i] = low(u[i]);
53             v[i] = low(v[i]);
54         }
55         for (int i = 1; i <= n; i++)
56         {
57             if (w[i] == 0) continue;
58             a = yl(u[i]);
59             b = yl(v[i]);
60             if (a != b) fa[a] = b;
61         }
62         int flag = 1;
63         for (int i = 1; i <= n; i++)
64         {
65             if (w[i] == 1) continue;
66             a = yl(u[i]);
67             b = yl(v[i]);
68             if (a == b)
69             {
70                 flag = 0;
71                 i = n;
72             }
73         }
74         puts(flag ? "YES" : "NO");
75     }
76 }