[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[N])表示包含DFS序为\(i\)的结点,是否有权值和为\(j\)的连通子图。设当前结点为\(x\),枚举子结点\(y_{1\sim k}\),则转移方程为\(f[x]=(f[y_1]\vee f[y_2]\vee\ldots\vee f[y_k])<<w[x]\)。
由于事实上对于每一个\(x\),我们并不需要知道\(f[x]\),而只需要利用它们求出\(f[root]\)的值,因此我们对于每一个\(x\)可以和上一个计算过的同级兄弟结点\(node[dfn[x]+sz[x]]\)合并。按DFS倒序枚举每一个结点\(x\),其DFS序为\(i\)。此时的状态转移方程为\(f[i]=(f[i+1]<<w[x])|f[i+sz[x]]\)。时间复杂度\(\mathcal O(\frac{nm\log n}\omega)\)。
源代码:
#include<cstdio>
#include<cctype>
#include<bitset>
#include<forward_list>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
constexpr int N=3001,M=1e5+1;
bool vis[N];
std::forward_list<int> e[N];
std::bitset<M> ans,f[N];
int n,m,w[N],size[N],sz[N],node[N],dfn[N],root,whole,min;
inline void add_edge(const int &u,const int &v) {
e[u].emplace_front(v);
e[v].emplace_front(u);
}
inline void clear() {
ans.reset();
for(register int i=1;i<=n;i++) {
vis[i]=false;
e[i].clear();
}
}
void dfs_root(const int &x,const int &par) {
size[x]=1;
int max=0;
for(auto &y:e[x]) {
if(y==par||vis[y]) continue;
dfs_root(y,x);
size[x]+=size[y];
max=std::max(max,size[y]);
}
max=std::max(max,whole-size[x]);
if(max<min) {
min=max;
root=x;
}
}
inline void get_root(const int &x,const int &sum) {
root=0;
min=n+1;
whole=sum;
dfs_root(x,0);
vis[root]=true;
}
void dfs(const int &x,const int &par) {
sz[x]=1;
dfn[x]=dfn[0]++;
node[dfn[x]]=x;
for(auto &y:e[x]) {
if(y==par||vis[y]) continue;
dfs(y,x);
sz[x]+=sz[y];
}
}
void solve(const int &x) {
dfn[0]=0;
dfs(x,0);
f[dfn[0]]=1;
for(register int i=dfn[0]-1;~i;i--) {
const int &y=node[i];
f[i]=(f[i+1]<<w[y])|f[i+sz[y]];
}
ans|=f[0];
for(auto &y:e[x]) {
if(vis[y]) continue;
get_root(y,size[y]);
solve(root);
}
}
int main() {
for(register int T=getint();T;T--) {
n=getint(),m=getint();
for(register int i=1;i<n;i++) {
add_edge(getint(),getint());
}
for(register int i=1;i<=n;i++) {
w[i]=getint();
}
get_root(1,n);
solve(root);
for(register int i=1;i<=m;i++) {
printf("%d",(int)ans[i]);
}
putchar('\n');
clear();
}
return 0;
}
[HDU6268]Master of Subgraph的更多相关文章
- 算法学习分析-点分治 HDU 6269 Master of Subgraph
首先给出定义 点分治是一种处理树上路径的工具 挂出一道题目来:Master of Subgraph 这道题目让你求所有联通子图加和所能产生数字,问你1到m之间,那些数字可以被产生 这道题目,假如我们利 ...
- Master of Subgraph
Problem E. Master of SubgraphYou are given a tree with n nodes. The weight of the i-th node is wi. G ...
- 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, no ...
- HDU - 6268: Master of Subgraph (分治+bitset优化背包)
题意:T组样例,给次给出一个N节点的点权树,以及M,问连通块的点权和sum的情况,输出sum=1到M,用0或者1表示. 思路:背包,N^2,由于是无向的连通块,所以可以用分治优化到NlgN. 然后背包 ...
- HDU 6268 Master of Subgraph (2017 CCPC 杭州 E题,树分治 + 树上背包)
题目链接 2017 CCPC Hangzhou Problem E 题意 给定一棵树,每个点有一个权值,现在我们可以选一些连通的点,并且把这点选出来的点的权值相加,得到一个和. 求$[1, m] ...
- CCPC 2016 杭州 E. Master of Subgraph(点分治+bitset优化DP)
题目链接:http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf 题意:给定一棵有 n 个结点的树和一个数 m,对于 i ∈ ...
- The 2017 China Collegiate Programming Contest, Hangzhou Site Solution
A: Super_palindrome 题面:给出一个字符串,求改变最少的字符个数使得这个串所有长度为奇数的子串都是回文串 思路:显然,这个字符串肯定要改成所有奇数位相同并且所有偶数位相同 那统计一下 ...
- 2017 CCPC杭州 题解
2017CCPC杭州题目PDF Problem A. Super-palindrome 题解: 给你一个字符串,每一步可以将一个字符替换为另一个字符,问你最少多少步可以使得,该字符串任意奇数子串为回文 ...
- ROS知识(20)----使用Master_API查询Master管理的节点话题服务内容
在一些应用中会需要获取master的uri地址,发布的话题,订阅的话题,发布的服务,节点的信息等等.这些功能我们通常可一通过rosnode list, rosnode info, rostopic l ...
随机推荐
- POJ3189:Steady Cow Assignment(二分+二分图多重匹配)
Steady Cow Assignment Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7482 Accepted: ...
- Java之戳中痛点 - (3)三目运算符的两个操作数类型尽量一致
先看一个例子: package com.test; public class TernaryOperator { public static void main(String[] args) { in ...
- CSS3学习笔记之loading动画
效果截图: HTML代码: <div class="divBox"> <div class="loader"> <div clas ...
- 【数据结构】bzoj1636/bzoj1699排队
Description 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置 ...
- 【IDEA】设置类头注释和方法注释
idea和eclipse的注释还是有一些差别的. 类头注释: 打开file->setting->Editor->Filr and Code Templates->Include ...
- 如何完全禁用或卸载Windows 10中的OneDrive
该功能占用很大的内存与CPU 详见http://os.51cto.com/art/201508/489371.htm
- [Leetcode Week5]Word Ladder
Word Ladder题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/word-ladder/description/ Description Give ...
- python学习笔记 协程
在学习异步IO模型前,先来了解协程 协程又叫做微线程,Coroutine 子程序或者成为函数,在所有语言中都是层级调用,比如a调用b,b调用c.c执行完毕返回,b执行完毕返回,最后a执行完毕返回 所以 ...
- C++实现高斯滤波器
在matlab中,我们经常用到高斯滤波器,生成滤波器一般都是这样的函数psf = fspecial('gauss', GaussSize, sigma),但是在vs2010中用到的高斯滤波器不能自 ...
- JQ面向对象
静态方法:某种类型才有的方法,这个方法干的事情只有类型本身有关,不受具体实例对象的影响,在C#语言中,它用static表示,VB中用share表示,而在jq中我们一般用$或者JQuery表示JQ类型, ...