zoukankan      html  css  js  c++  java
  • 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

    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("
    ");
        }
        return 0;
    }
  • 相关阅读:
    SQL优化,解决系统运行效率瓶颈
    C#中 哪些是值类型 哪些是引用类型
    C#异常类相关总结
    对象 序列化 字节流 传输
    给数组中的每个元素赋值
    对象转化为 xml字符串
    .NET BETWEEN方法
    Datatable To List<Entity>
    ajax原理
    gulp记录
  • 原文地址:https://www.cnblogs.com/wmj6/p/10805776.html
Copyright © 2011-2022 走看看