zoukankan      html  css  js  c++  java
  • hdu6268(求是否存在子图点权和为固定的i,bitset+点分治)

    题:http://acm.hdu.edu.cn/showproblem.php?pid=6268

    题意:给定n个点的树,和一个数m,求树中是否子图点权和为1~m

    分析:关键是找subgraph,平时的点分治都是找路径的,这时我们可以结合bitset,每个节点都是一个bitset,每次父亲u保留自己状态,然后把自己状态给儿子v,再让儿子取延申,最后和u的bitset合并,也就顺理成章地表示为包含u的子图能合成的数的集合,再|给答案即可

    #include<bits/stdc++.h>
    using  namespace std;
    const int M=3e3+5;
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    typedef long long ll;
    int n,m;
    ll sz[M];
    int val[M],vis[M],head[M],reco,total,tot,root;
    struct node{
        int v,nextt;
        ll w;
    }e[M<<1];
    
    void addedge(int u,int v){
        e[tot].v=v;
        e[tot].nextt=head[u];
        head[u]=tot++;
    }
    
    void dfsroot(int u,int f){
        sz[u]=1;
        ll maxson=0;
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(v!=f&&!vis[v]){
                dfsroot(v,u);
                sz[u]+=sz[v];
                maxson=max(maxson,sz[v]);
            }
        }
        maxson=max(maxson,total-sz[u]);
        if(maxson<reco)
            root=u,reco=maxson;
    }
    bitset<N>b[M],ans;
    void calc(int u,int f){
        b[u]<<=val[u];
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(v==f||vis[v])
                continue;
            b[v]=b[u];
            calc(v,u);
            b[u]|=b[v];
        }
    }
    void solve(int u,int f){
        vis[u]=1;
        b[u].reset();b[u].set(0);
        calc(u,f);
        ans|=b[u];
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(v!=f&&!vis[v]){
                total=sz[v];
                reco=inf;
                dfsroot(v,u);
                solve(root,0);
            }
        }
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            ans.reset();
            tot=0;
            for(int i=1;i<=n;i++) head[i]=-1,vis[i]=0;
            for(int u,v,i=1;i<n;i++){
                scanf("%d%d",&u,&v);
                addedge(u,v),addedge(v,u);
            }
            for(int i=1;i<=n;i++) scanf("%d",&val[i]);
            total=n;
            reco=inf;
            dfsroot(1,0);
            solve(root,0);
            for(int i=1;i<=m;i++)
                if(ans[i]==1) putchar('1');
                else putchar('0');
            puts("");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    12-五子棋游戏:享元模式
    11-制作糖醋排骨:外观模式
    10-蒸馒头:装饰者模式
    09-公司层级结构:组合模式
    08-开关与电灯:桥接模式
    07-电源转换:适配器模式
    将博客搬至CSDN
    iview和element中日期选择器快捷选项的定制控件
    详解AJAX工作原理以及实例讲解(通俗易懂)
    最全肌肉锻炼动图
  • 原文地址:https://www.cnblogs.com/starve/p/13837568.html
Copyright © 2011-2022 走看看