hdu 6268 Master of Subgraph(点分治+bitset)

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

扫描二维码关注公众号,回复: 6108180 查看本文章

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;
}

猜你喜欢

转载自www.cnblogs.com/wmj6/p/10805776.html