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("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wmj6/p/10805776.html

时间: 2024-11-05 18:48:57

hdu 6268 Master of Subgraph(点分治+bitset)的相关文章

HDU - 6268: Master of Subgraph (分治+bitset优化背包)

题意:T组样例,给次给出一个N节点的点权树,以及M,问连通块的点权和sum的情况,输出sum=1到M,用0或者1表示. 思路:背包,N^2,由于是无向的连通块,所以可以用分治优化到NlgN. 然后背包可以用bitset优化.注意不要想着背包合并背包,背包只能合并单点. #include<bits/stdc++.h> #define pb push_back #define rep(i,a,b) for(int i=a;i<=b;i++) #define Gv G[u][i] #defin

[HDU6268]Master of Subgraph

[HDU6268]Master of Subgraph 题目大意: 一棵\(n(n\le3000)\)个结点的树,每个结点的权值为\(w_i\).给定\(m(m\le10^5)\),对于任意\(i\in[1,m]\),问书中是否有一个连通子图的权值和等于\(i\). 思路: 重心剖分.考虑处理当前处理出的以重心\(x\)为根的子树.首先求出当前子树的DFS序,设用\(node[i]\)表示DFS序为\(i\)的结点编号.考虑动态规划,用\(f[i][j]\)(std::bitset<M> f[

hdu 4858 项目管理 (图的分治)

项目管理 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 252    Accepted Submission(s): 88 Problem Description 我们建造了一个大项目!这个项目有n个节点,用很多边连接起来,并且这个项目是连通的! 两个节点间可能有多条边,不过一条边的两端必然是不同的节点. 每个节点都有一个能量值. 现

HDU 5016 Mart Master II (树上点分治)

题目地址:HDU 5016 先两遍DFS预处理出每个点距最近的基站的距离与基站的编号. 然后找重心,求出每个点距重心的距离,然后根据dis[x]+dis[y] < d[y],用二分找出当前子树中不会被占领的数量,总点数减去即是被占领的数量.这样就可以求出每个点最多占领的点的数量.然后找最大值即可. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue&g

HDU 5324 Boring Class【cdq分治】

这就是一个三维排序的问题,一维递减,两维递增,这样的问题用裸的CDQ分治恰好能够解决. 如同HDU 4742(三维排序,一个三维都是递增的) 由于最小字典序比較麻烦,所以要从后面往前面做分治.每一个点的dp值表示以这个点为起点.最长能够延伸多长. 本来是想依照Li排序,可是这样做在cdq的时候实在是太难以处理了.所以就依照idx排序.也就是不须要排序. 然后依照Ri排序,对于左边,保证右边的每一个R值大于左边的值.并用树状数组维护Li(由于Li须要递减.所以树状数组恰好能够维护右边的Li小于左边

HDU 3507 Print Article(CDQ分治+分治DP)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3507 [题目大意] 将长度为n的数列分段,最小化每段和的平方和. [题解] 根据题目很容易得到dp[j]=min(dp[k]+(s[j]-s[k])2),因为是从前往后转移,且决策单调,因此在CDQ分治的同时进行分治DP即可. [代码] #include <cstdio> typedef long long LL; const int N=500005; int n,M,t; LL f[N],

HDU 5730 Shell Necklace(CDQ分治+FFT)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3,则其权值为5,现在有长度为n的字段,求通过不同拆分得到的字段权值乘积和. [题解] 记DP[i]表示长度为i时候的答案,DP[i]=sum_{j=0}^{i-1}DP[j]w[i-j],发现是一个卷积的式子,因此运算过程可以用FFT优化,但是由于在计算过程中DP[j]是未知值,顺次计算复杂度是O(

hdu 5745 La Vie en rose(dp+bitset)

题目链接:hdu 5745 La Vie en rose 题意: 给两个字符串 a 和 b ,b可以进行变换,规则是可以任意交换相邻两个字符的位置,但是不可以有交叉(例如3和4交换,5和6交换 互不影响,但是2和3,3和4就不可以).求a中每一个位置能不能匹配b或b变换得到的子串. 题解: 考虑dp,dp[i][j][k]表示a[i]和b[j]匹配,k为1表示j未做交换,k=0表示j和j-1进行交换,k=2表示j和j+1进行交换. 然后bitset优化一下常数. dp方程为: dpi,j,0=d

hdu 5313 Bipartite Graph 完全二分图 深搜 bitset应用

Bipartite Graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 577    Accepted Submission(s): 154 Problem Description Soda has a bipartite graph with n vertices and m undirected edges. Now he