bitset用法
bitset<B_Length> array[A_SIZE] 创建一个长度为B_Length,大小为A_SIZE的数组
bitset<B> a(n) 初始化一个值为n的bitset
.reset() 将所有位初始化为0
.set() 将所有位初始化为1
.any() 是否有某一位为1
= x && x belong to int 将x的值赋给bitset转化为2进制表示
bitset支持左移右移各种位运算操作
树分治
对于每个点,如果要取某点的子节点,那么必然会经过该节点, 故合并的时候有 b[v]<<val[v]操作
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 3e3 + 5;
const int MAX_M = 1e5 + 5;
vector<int> G[MAX_N];
int s[MAX_N], d[MAX_N], f[MAX_N], root, sz, n, m, val[MAX_N];
bool used[MAX_N];
bitset<MAX_M> b[MAX_N], ans;
void get_r(int u, int p) {
f[u] = 0; s[u] = 1;
for (auto v : G[u]) {
if (used[v] || v == p) continue;
get_r(v, u);
f[u] = max(f[u], s[v]);
s[u] += s[v];
}
f[u] = max(f[u], sz - f[u]);
if (f[u] < f[root]) root = u;
}
void get_v(int u, int p) {
b[u] <<= val[u];
s[u] = 1;
for (auto v : G[u]) {
if (!used[v] && v != p) {
b[v] = b[u];
get_v(v, u);
b[u] |= b[v];
s[u] += s[v];
}
}
}
void solve(int u) {
used[u] = true;
b[u] = 1;
get_v(u, 0);
ans |= b[u];
for (auto v : G[u]) {
if (!used[v]) {
sz = s[v]; root = 0;
get_r(v, u);
solve(root);
}
}
}
int main() {
int T; cin >> T; while(T--) {
//clear
cin >> n >> m;
memset(used, false, sizeof used);
for (int i = 1; i <= n; i++) G[i].clear();
ans.reset();
for (int i = 0; i < n - 1; i++) {
int a, b; scanf("%d%d", &a, &b);
G[a].push_back(b);
G[b].push_back(a);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &val[i]);
}
f[0] = n + 5;
sz = n;
get_r(1, root);
solve(root);
for (int i = 1; i <= m; i++) {
printf("%d", (int)ans[i]);
}
puts("");
}
}