hdoj5909 Tree Cutting(点分治+树上dp转序列dp)
题目链接:https://vjudge.net/problem/HDU-5909
题意:给一颗树,结点带权值v[i]<m。求异或和为k的子树个数(0<=k<m)。
思路:
首先点分治处理一颗树,跑一遍dfs得到该树的dfs序。然后我们用序列dp来做,用dp[i][j]表示必须包括重心,处理序列中第i个结点时异或和为j的子树个数,因为必须包括重心,所以能做到不重不漏。
现在讨论结点i已经决策完毕
如果选i+1:dp[i+1][j^v[id[i+1]]]+=dp[i][j]。(id[i+1]表示dfs序列中第i+1个结点的编号)。
如果不选i+1:dp[i+sz[id[i+1]]][j]+=dp[i][j]。(因为如果i+1不选的话,以i+1为根的子树里的结点都不能选,sz[i]表示结点i的子树的大小)。
最后ans[i]+=dp[t][i],t为该子树的大小。
AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; const int maxn=1e3+;
const int inf=0x3f3f3f3f;
const int MOD=1e9+;
typedef long long LL;
struct node{
int v,nex;
}edge[maxn<<];
int T,n,m,V[maxn],head[maxn],cnt;
int sz[maxn],mson[maxn],Min,root,size,vis[maxn],id[maxn],t;
LL ans[maxn],dp[maxn][maxn]; void adde(int u,int v){
edge[++cnt].v=v;
edge[cnt].nex=head[u];
head[u]=cnt;
} void getroot(int u,int fa){
sz[u]=,mson[u]=;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]||v==fa) continue;
getroot(v,u);
sz[u]+=sz[v];
mson[u]=max(mson[u],sz[v]);
}
mson[u]=max(mson[u],size-sz[u]);
if(mson[u]<Min) Min=mson[u],root=u;
} void dfs(int u,int fa){
sz[u]=,id[++t]=u;
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(v==fa||vis[v]) continue;
dfs(v,u);
sz[u]+=sz[v];
}
} void solve(int u){
t=;
dfs(u,);
for(int i=;i<=t;++i)
for(int j=;j<m;++j)
dp[i][j]=;
dp[][V[u]]=;
for(int i=;i<=t-;++i)
for(int j=;j<m;++j){
dp[i+][j^V[id[i+]]]=(dp[i+][j^V[id[i+]]]+dp[i][j])%MOD;
dp[i+sz[id[i+]]][j]=(dp[i+sz[id[i+]]][j]+dp[i][j])%MOD;
}
for(int i=;i<m;++i)
ans[i]=(ans[i]+dp[t][i])%MOD;
} void fenzhi(int u,int ssize){
vis[u]=;
solve(u);
for(int i=head[u];i;i=edge[i].nex){
int v=edge[i].v;
if(vis[v]) continue;
Min=inf,root=,size=sz[v];
getroot(v,);
fenzhi(root,size);
}
} int main(){
scanf("%d",&T);
while(T--){
cnt=;
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
head[i]=vis[i]=;
for(int i=;i<=n;++i)
scanf("%d",&V[i]);
for(int i=;i<m;++i)
ans[i]=;
for(int i=;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
adde(u,v);
adde(v,u);
}
Min=inf,root=,size=n;
getroot(,);
fenzhi(root,n);
for(int i=;i<m;++i){
printf("%lld",ans[i]);
if(i!=m-) printf(" ");
}
printf("\n");
}
return ;
}
hdoj5909 Tree Cutting(点分治+树上dp转序列dp)的更多相关文章
- hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...
- hdu 5909 Tree Cutting —— 点分治
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治,每次的 rt 是必选的点: 考虑必须选根的一个连通块,可以DP,决策就是在每个子树中决定选不 ...
- 【HDU 5909】 Tree Cutting (树形依赖型DP+点分治)
Tree Cutting Problem Description Byteasar has a tree T with n vertices conveniently labeled with 1,2 ...
- HDU-6881 Tree Cutting (HDU多校D10T5 点分治)
HDU-6881 Tree Cutting 题意 \(n\) 个点的一棵树,要求删除尽量少的点,使得删点之后还是一棵树,并且直径不超过 \(k\),求删除点的数量 分析 补题之前的一些错误想法: 尝试 ...
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- hdu 5909 Tree Cutting [树形DP fwt]
hdu 5909 Tree Cutting 题意:一颗无根树,每个点有权值,连通子树的权值为异或和,求异或和为[0,m)的方案数 \(f[i][j]\)表示子树i中经过i的连通子树异或和为j的方案数 ...
- POJ 2378.Tree Cutting 树形dp 树的重心
Tree Cutting Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4834 Accepted: 2958 Desc ...
- POJ 2378 Tree Cutting 3140 Contestants Division (简单树形dp)
POJ 2378 Tree Cutting:题意 求删除哪些单点后产生的森林中的每一棵树的大小都小于等于原树大小的一半 #include<cstdio> #include<cstri ...
- HDU 5909 Tree Cutting(FWT+树形DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5909 [题目大意] 给出一棵树,其每棵连通子树的价值为其点权的xor和, 问有多少连通子树的价值为 ...
随机推荐
- SQL SERVER 表添加新字段
SQL SERVER 表添加新字段 ALTER TABLE doc_exa ADD column_b VARCHAR(20) NULL; -- doc_exa 是表名 -- column_b 是新加的 ...
- HDU 5486 Difference of Clustering 暴力模拟
Difference of Clustering HDU - 5486 题意:有n个实体,新旧两种聚类算法,每种算法有很多聚类,在同一算法里,一个实体只属于一个聚类,然后有以下三种模式. 第一种分散, ...
- 用python来抓取“煎蛋网”上面的美女图片,尺度很大哦!哈哈
所用Python环境为:python 3.3.2 用到的库为:urllib.request re 废话不多说,先上代码: import urllib.request import re #获 ...
- Mybatis源码学习之DataSource(七)_1
简述 在数据持久层中,数据源是一个非常重要的组件,其性能直接关系到整个数据持久层的性能.在实践中比较常见的第三方数据源组件有Apache Common DBCP.C3P0.Proxool等,MyBat ...
- CF1204B
CF1204B-Mislove Has Lost an Array 题意: 给你n,l,r 表示在区间1-n内至少有l个不相同的数至多有r个不相同的数,而且这些数不是1就是偶数而且每个偶数/2得到的数 ...
- 图论——Floyd算法拓展及其动规本质
一.Floyd算法本质 首先,关于Floyd算法: Floyd-Warshall算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路径的算法.算法的单个执行将找到所有顶点对之间的最短路径 ...
- maven上传jar包(oracle jdbc驱动)
由于Oracle授权问题,Maven3不提供Oracle JDBC driver,为了在Maven项目中应用Oracle JDBC driver,必须手动添加到本地仓库.一.首先要得到Oracle J ...
- InnoDB缓存---InnoDB Buffer Pool
InnoDB Buffer Pool 定义 对于InnoDB存储引擎,不管用户数据还是系统数据都是以页的形式存储在表空间进行管理的,其实都是存储在磁盘上的. 当InnoDB处理客户端请求,需要读取某页 ...
- 线性dp,分层图思想
题目大意:给你一串数字,一串运算符,求递推用完运算符时答案的最大值----->线性dp dp[i][j] i表示所用数字的个数 j表示所用字符的个数 分层图思想 所有字符必须用完 所以取最后 ...
- PostgreSQL 当月最后一天的工作日 , 计算日期是星期几
可以用pg自带函数select extract(dow from current_date),之所以没用主要是展示一下通过数学方法计算日期的原理. drop function if exists ge ...