zoukankan      html  css  js  c++  java
  • Hdu 6268 点分治 树上背包 bitset 优化

    给你一颗大小为n(3000)的树,树上每个点有点权(100000),再给你一个数m(100000)

    i为1~m,问树中是否存在一个子图,使得权值为i.

    每次solve到一个节点 用一个bitset维护所有经过它的链的取值(calc前要先初始化当前节点的bitset)

    复杂度为nlognm/64

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define mst(a,b) memset((a),(b),sizeof(a))
    #define mp(a,b) make_pair(a,b)
    #define pi acos(-1)
    #define pii pair<int,int>
    #define pb push_back
    const int INF = 0x3f3f3f3f;
    const double eps = 1e-6;
    const int maxn = 3e3 + 10;
    const int maxm = 1e5 + 10;
    const ll mod =  998244353;
    
    int n,m;
    vector<int>vec[maxn];
    bool used[maxn];
    int a[maxn],root,sz[maxn],son[maxn],all;
    
    void getroot(int u,int fa) {
        sz[u] = 1, son[u] = 0;
        for(int i = 0; i < vec[u].size(); i++) {
            int v = vec[u][i];
            if(used[v] || v == fa) continue;
            getroot(v,u);
            sz[u] += sz[v];
            son[u] = max(son[u],sz[v]);
        }
        son[u] = max(son[u],all - son[u]);
        if(son[u] < son[root]) root = u;
    }
    
    bitset<maxm>bit[maxn],ans;
    
    void calc(int u,int fa) {
        sz[u] = 1, bit[u] <<= a[u];
        for(int i = 0; i < vec[u].size(); i++) {
            int v = vec[u][i];
            if(used[v] || v == fa) continue;
            bit[v] = bit[u];
            calc(v,u);
            sz[u] += sz[v];
            bit[u] |= bit[v];
        }
    }
    
    void solve(int u) {
        used[u] = true;
        bit[u].reset(), bit[u].set(0);
        calc(u,0);
        ans |= bit[u];
        for(int i = 0; i < vec[u].size(); i++) {
            int v = vec[u][i];
            if(used[v]) continue;
            root = 0;
            all = sz[v];
            getroot(v,0);
            solve(root);
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        int t;
        scanf("%d",&t);
        while(t--) {
            ans.reset();
            scanf("%d%d",&n,&m);
            for(int i = 0; i <= n; i++) vec[i].clear(),used[i] = false;
            for(int i = 1; i < n; i++) {
                int u,v;
                scanf("%d%d",&u,&v);
                vec[u].push_back(v);
                vec[v].push_back(u);
            }
            for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
            root = 0;
            son[0] = 1e9;
            all = n;
            getroot(1,0);
            solve(root);
            for(int i = 1; i <= m; i++) printf("%d",(int)ans[i]);
            printf("
    ");
        }
        return 0;
    }

     

  • 相关阅读:
    【LeetCode】456. 132 Pattern
    【Python&Sort】QuickSort
    Python虚拟环境的配置
    【LeetCode】459. Repeated Substring Pattern
    【LeetCode】462. Minimum Moves to Equal Array Elements II
    【LeetCode】20. Valid Parentheses
    radio 获取选中值
    页面加载时自动执行(加载)js的几种方法
    加一个字段: updateTime 更新时间
    多用户同时处理同一条数据解决办法
  • 原文地址:https://www.cnblogs.com/Aragaki/p/10590513.html
Copyright © 2011-2022 走看看