E - Master of Subgraph HDU - 6268 点分治 + bitset

刚好最近做点分治,不过当时没做出来,第一次用bitset优化,感觉还是挺巧妙地。

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<bitset>

using namespace std;
const int maxn = 3010;
bitset<100007>b[3010];
struct node
{
    int next, to;
};
node edge[maxn<<1];
int son[maxn], sz[maxn], val[maxn], head[maxn], vis[maxn];
int tot, all, root;
bitset<100007>ans;

void add(int u, int to)
{
    edge[tot] = (node){head[u], to};
    head[u] = tot++;
}

void getroot(int x, int fa)
{
    sz[x] = 1;
    son[x] = 0;
    for(int i = head[x]; ~i; i = edge[i].next)
    {
        int to = edge[i].to;
        if(to == fa || vis[to]) continue;
        getroot(to, x);
        sz[x] += sz[to];
        son[x] = max(son[x], sz[to]);
    }
    son[x] = max(son[x], all - sz[x]);
    if(son[x] < son[root]) root = x;
}

void cal(int x, int fa)
{
    b[x] <<= val[x];
    for(int i = head[x]; ~i; i =edge[i].next)
    {
        int to = edge[i].to;
        if(to == fa || vis[to]) continue;
        b[to] = b[x];
        cal(to, x);
        b[x] |= b[to];

    }
}

void work(int x)
{
    vis[x] = 1;
    b[x].reset();
    b[x].set(0);
    cal(x, 0);
    ans |= b[x];
    for(int i = head[x]; ~i; i = edge[i].next)
    {
         int to = edge[i].to;
         if(vis[to]) continue;
         all = sz[to], root = 0;
         getroot(to, 0);
         work(root);
    }
}

int main()
{
   int t;
   scanf("%d", &t);
   while(t--)
   {
       int n, m;
       tot = 0;
       memset(head, -1, sizeof(head));
       memset(vis, 0, sizeof(vis));
       scanf("%d%d", &n, &m);
       for(int i = 1; i < n; i++)
       {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
       }
       for(int i = 1; i <= n; i++)
        scanf("%d", &val[i]);
       root = 0;
       all = n;
       ans.reset();
       son[0] = 0x3f3f3f3f;
       getroot(1, 0);
       work(root);
       for(int i = 1; i <= m; i++)
       {
           if(i == m)
            printf("%d\n", (int)ans[i]);
           else
            printf("%d", (int)ans[i]);
       }
   }
   return 0;
}

发布了40 篇原创文章 · 获赞 13 · 访问量 850

猜你喜欢

转载自blog.csdn.net/weixin_43891021/article/details/102748430