题目链接: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)的更多相关文章

  1. hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...

  2. hdu 5909 Tree Cutting —— 点分治

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治,每次的 rt 是必选的点: 考虑必须选根的一个连通块,可以DP,决策就是在每个子树中决定选不 ...

  3. 【HDU 5909】 Tree Cutting (树形依赖型DP+点分治)

    Tree Cutting Problem Description Byteasar has a tree T with n vertices conveniently labeled with 1,2 ...

  4. HDU-6881 Tree Cutting (HDU多校D10T5 点分治)

    HDU-6881 Tree Cutting 题意 \(n\) 个点的一棵树,要求删除尽量少的点,使得删点之后还是一棵树,并且直径不超过 \(k\),求删除点的数量 分析 补题之前的一些错误想法: 尝试 ...

  5. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  6. hdu 5909 Tree Cutting [树形DP fwt]

    hdu 5909 Tree Cutting 题意:一颗无根树,每个点有权值,连通子树的权值为异或和,求异或和为[0,m)的方案数 \(f[i][j]\)表示子树i中经过i的连通子树异或和为j的方案数 ...

  7. POJ 2378.Tree Cutting 树形dp 树的重心

    Tree Cutting Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4834   Accepted: 2958 Desc ...

  8. POJ 2378 Tree Cutting 3140 Contestants Division (简单树形dp)

    POJ 2378 Tree Cutting:题意 求删除哪些单点后产生的森林中的每一棵树的大小都小于等于原树大小的一半 #include<cstdio> #include<cstri ...

  9. HDU 5909 Tree Cutting(FWT+树形DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5909 [题目大意] 给出一棵树,其每棵连通子树的价值为其点权的xor和, 问有多少连通子树的价值为 ...

随机推荐

  1. laravel各种请求类

    curl请求类 composer require php-curl-class/php-curl-class

  2. CKEditor从word粘贴问题

    最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...

  3. javascript JSON.parse and JSON.stringify

    var jstu = '{"name": "xiaoqiang", "age": 18}'; console.log(jstu); var ...

  4. Win2008 R2 IIS FTP防火墙的配置

    注意以下两个选项要在防火墙下开启,否则将会访问失败.

  5. 【线性代数】4-2:投影(Porjections)

    title: [线性代数]4-2:投影(Porjections) categories: Mathematic Linear Algebra keywords: Projections Project ...

  6. 【CUDA 基础】5.1 CUDA共享内存概述

    title: [CUDA 基础]5.1 CUDA共享内存概述 categories: - CUDA - Freshman tags: - CUDA共享内存模型 - CUDA共享内存分配 - CUDA共 ...

  7. Java事务不回滚的原因总结

    1.首先要检查数据的引擎,InnoDB支持事务,MyIsam不支持事务 2.  默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚.     spring aop  异常 ...

  8. AcWing:178. 第K短路(A*)

    给定一张N个点(编号1,2…N),M条边的有向图,求从起点S到终点T的第K短路的长度,路径允许重复经过点或边. 注意: 每条最短路中至少要包含一条边. 输入格式 第一行包含两个整数N和M. 接下来M行 ...

  9. Linux 系统设置命令之ulimit

    定义 ulimit 用于限制 shell 启动进程所占用的资源,支持以下各种类型的限制:所创建的内核文件的大小.进程数据块的大小.Shell 进程创建文件的大小.内存锁住的大小.常驻内存集的大小.打开 ...

  10. Java中局部变量、实例变量和静态变量在方法区、栈内存、堆内存中的分配

    转自:https://blog.csdn.net/leunging/article/details/80599282 感谢CSDN博主「leunging」的总结分享 ———————————————— ...