刚好最近做点分治,不过当时没做出来,第一次用bitset优化,感觉还是挺巧妙地。
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<bitset>
using namespace std;
const int maxn = 3010;
bitset<100007>b[3010];
struct node
{
int next, to;
};
node edge[maxn<<1];
int son[maxn], sz[maxn], val[maxn], head[maxn], vis[maxn];
int tot, all, root;
bitset<100007>ans;
void add(int u, int to)
{
edge[tot] = (node){head[u], to};
head[u] = tot++;
}
void getroot(int x, int fa)
{
sz[x] = 1;
son[x] = 0;
for(int i = head[x]; ~i; i = edge[i].next)
{
int to = edge[i].to;
if(to == fa || vis[to]) continue;
getroot(to, x);
sz[x] += sz[to];
son[x] = max(son[x], sz[to]);
}
son[x] = max(son[x], all - sz[x]);
if(son[x] < son[root]) root = x;
}
void cal(int x, int fa)
{
b[x] <<= val[x];
for(int i = head[x]; ~i; i =edge[i].next)
{
int to = edge[i].to;
if(to == fa || vis[to]) continue;
b[to] = b[x];
cal(to, x);
b[x] |= b[to];
}
}
void work(int x)
{
vis[x] = 1;
b[x].reset();
b[x].set(0);
cal(x, 0);
ans |= b[x];
for(int i = head[x]; ~i; i = edge[i].next)
{
int to = edge[i].to;
if(vis[to]) continue;
all = sz[to], root = 0;
getroot(to, 0);
work(root);
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
int n, m;
tot = 0;
memset(head, -1, sizeof(head));
memset(vis, 0, sizeof(vis));
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
for(int i = 1; i <= n; i++)
scanf("%d", &val[i]);
root = 0;
all = n;
ans.reset();
son[0] = 0x3f3f3f3f;
getroot(1, 0);
work(root);
for(int i = 1; i <= m; i++)
{
if(i == m)
printf("%d\n", (int)ans[i]);
else
printf("%d", (int)ans[i]);
}
}
return 0;
}