You are given a tree with n nodes. The weight of the i-th node is wi. Given a positive integer m, now you need to judge that for every integer i in [1,m] whether there exists a connected subgraph which the sum of the weights of all nodes is equal to i.
Input:
The first line contains an integer T (1 ≤ T ≤ 15) representing the number of test cases. For each test case, the first line contains two integers n (1 ≤ n ≤ 3000) and m (1 ≤ m ≤ 100000), which are mentioned above. The following n−1 lines each contains two integers ui and vi (1 ≤ ui,vi ≤ n). It describes an edge between node ui and node vi. The following n lines each contains an integer wi (0 ≤ wi ≤ 100000) represents the weight of the i-th node. It is guaranteed that the input graph is a tree.
Output :
For each test case, print a string only contains 0 and 1, and the length of the string is equal to m. If there is a connected subgraph which the sum of the weights of its nodes is equal to i, the i-th letter of string is 1 otherwise 0.
Example
standard input
2
4 10
1 2
2 3
3 4
3 2 7 5
6 10
1 2
1 3
2 5
3 4
3 6
1 3 5 7 9 11
standard output
0110101010
1011111010
题意:给你一棵树 询问现在小于等于m的权值出现情况 权值是任意联通子树的点权和
思路:对于第i个节点 我们把问题的规模分成 包含i点的子树 不包含i点的子树 对于第二种情况 可以递归求解
在计算经过i点的图的权值的时候我们可以用bitset来标记 很巧妙 具体操作可以看代码
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<cmath> #include<set> #include<list> #include<deque> #include<map> #include<queue> #define ll long long int using namespace std; inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;} int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1}; int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1}; const int inf=0x3f3f3f3f; const ll mod=1e9+7; int head[3007],vis[3007]; int d[3007],val[3007]; struct node{ int to,next; }; node edge[6007]; int cnt,n,m; void init(){ cnt=0; memset(head,0,sizeof(head)); memset(vis,0,sizeof(vis)); } void add(int from,int to){ edge[++cnt].to=to; edge[cnt].next=head[from]; head[from]=cnt; } int son[3007]; int now_size,sz,root; void find_root(int u,int fa){ son[u]=1; int res=-inf; for(int i=head[u];i;i=edge[i].next){ if(vis[edge[i].to]||edge[i].to==fa) continue; int to=edge[i].to; find_root(to,u); son[u]+=son[to]; res=max(res,son[to]); } res=max(res,sz-son[u]); if(res<now_size) now_size=res,root=u; } bitset<100007>bits[3007],ans; void solve(int u,int fa){ bits[u]<<=val[u]; //把之前出现过的权值都加上val[u] for(int i=head[u];i;i=edge[i].next){ if(vis[edge[i].to]||edge[i].to==fa) continue; int to=edge[i].to; bits[to]=bits[u]; //向下传递 solve(to,u); bits[u]|=bits[to]; //收集信息 } } void dfs(int u){ //分治 vis[u]=1; bits[u].reset(); bits[u].set(0); //把0位置的置1 solve(u,0); ans|=bits[u]; int totsz=sz; for(int i=head[u];i;i=edge[i].next){ if(vis[edge[i].to]) continue; int to=edge[i].to; now_size=inf; root=0; sz=son[to]>son[u]?totsz-son[u]:son[to]; find_root(to,0); dfs(root); } } int main(){ int t; scanf("%d",&t); while(t--){ init(); ans.reset(); scanf("%d%d",&n,&m); for(int i=1;i<n;i++){ int from,to; scanf("%d%d",&from,&to); add(from,to); add(to,from); } for(int i=1;i<=n;i++) scanf("%d",&val[i]); now_size=inf,sz=n,root=0; find_root(1,0); dfs(root); for(int i=1;i<=m;i++) printf("%d",(int)ans[i]); printf("\n"); } return 0; }
原文地址:https://www.cnblogs.com/wmj6/p/10805776.html