2+ doors

2+ doors

Created by LXC on Sat Sep 23 11:55:26 2023

https://codeforces.com/problemset/problem/1715/D

ranting: 1900

tag: 2-sat, bitmasks, graphs, greedy

problem

给出一个长度为n的数组a,以及q个条件,每个条件都包含三个数i,j,x。意味着$a_i|a_j = x$

求满足所有条件的最小字典序的数组。

solution

$a_i|a_j = x$,无论是$a_i$还是$a_j$二进制的1应该都是$x$二进制位上1的子集。

我们初始每个$a_i$二进制全为1,然后通过与运算,得到每个$a_i$初步的答案。

对于$a_i$,可以对应多个$a_j$的条件$a_i|a_j = x$。

我们由小到大遍历下标,对于$a_i$应该是所有$a_j$二进制位去除x后合并的结果。

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

#include <bits/stdc++.h>
#define SINGLE_INPUT
#define ll long long
#define ull unsigned long long
#define N 500005
#define MOD 998244353
using namespace std;


void sol() {
int n, q;
cin >> n >> q;
vector<vector<pair<ll, ll>>> g(n+1);
vector<ll> ans(n+1, (1LL<<31)-1);
for (int i=0; i<q; i++) {
ll x, y, v;
cin >> x >> y >> v;
g[x].emplace_back(y, v);
g[y].emplace_back(x, v);
ans[x] &= v;
ans[y] &= v;
}
for (int i=1; i<=n; i++) {
int res = 0;
for (auto [j, v]: g[i]) {
if (j == i) {
res = v;
break;
}
res |= ans[j]^v;
}
ans[i] = res;
}
for (int i=1; i<=n; i++) {
cout << ans[i] << " ";
} cout << endl;
}

int main() {
cout << setprecision(15) << fixed;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifndef SINGLE_INPUT
int t;
cin >> t;
while (t--) {
sol();
}
#else
sol();
#endif
return 0;
}