题意:T组样例,给次给出一个N节点的点权树,以及M,问连通块的点权和sum的情况,输出sum=1到M,用0或者1表示。
思路:背包,N^2,由于是无向的连通块,所以可以用分治优化到NlgN。 然后背包可以用bitset优化。注意不要想着背包合并背包,背包只能合并单点。
#include<bits/stdc++.h>
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Gv G[u][i]
#define feach(i,u) for(int i=0;i<G[u].size();i++)
using namespace std;
const int maxn=;
vector<int>G[maxn];
bitset<>s[maxn],ans;
int a[maxn],sz[maxn],son[maxn],vis[maxn],rt;
void dfs(int u,int f,int n){
sz[u]=; son[u]=;
feach(i,u){
if(Gv==f||vis[Gv]) continue;
dfs(Gv,u,n);
sz[u]+=sz[Gv];
son[u]=max(son[u],sz[Gv]);
}
son[u]=max(son[u],n-son[u]);
if(son[u]<son[rt]) rt=u;
}
void getdp(int u,int f){
sz[u]=; s[u]<<=a[u];
feach(i,u){
if(Gv==f||vis[Gv]) continue;
s[Gv]=s[u];
getdp(Gv,u);
sz[u]+=sz[Gv];
s[u]|=s[Gv];
}
}
void solve(int u){
vis[u]=; s[u].reset();s[u][]=;
getdp(u,-); ans|=s[u];
feach(i,u){
if(!vis[Gv]){
rt=; dfs(Gv,-,sz[Gv]);
solve(rt);
}
}
}
int main()
{
int T,N,M;
scanf("%d",&T); son[]=;
while(T--){
scanf("%d%d",&N,&M);
rep(i,,N) G[i].clear(),vis[i]=;
ans.reset();
rep(i,,N-){
int u,v; scanf("%d%d",&u,&v);
G[u].pb(v); G[v].pb(u);
}
rep(i,,N) scanf("%d",&a[i]);
rt=; dfs(,-,N);
solve(rt);
rep(i,,M) printf("%d",(int)ans[i]);
puts("");
}
return ;
}