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和, 问有多少连通子树的价值为 ...
随机推荐
- 初入SG-UAP
初入SG-UAP SpriderMan 关注 2019.06.19 14:10 字数 1130 阅读 10评论 0喜欢 0 初次接触SG-UAP,将自己的见解以文字形式记录下来,希望能对初入的伙伴们有 ...
- C++中时间转换
所需头文件 #include <chrono> #include <time.h> auto now = std::chrono::system_clock::now(); s ...
- tensorflow 框架图
- kong-dashbord本地安装gulp打包报错的解决办法
本地安装kong-dashbord执行npm run build 报如下错误 gulp[]: ../src/node_contextify.cc::]->IsString()' failed. ...
- codeforces723E
One-Way Reform CodeForces - 723E There are n cities and m two-way roads in Berland, each road connec ...
- AcWing:237. 程序自动分析(离散化 + 并查集)
在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3,…x1,x2,x3,…代表程序中出现的变量,给定n个形如xi=xjxi=x ...
- TCP报头格式
1.端口号:用来标识同一台计算机的不同的应用进程. 1)源端口:源端口和IP地址的作用是标识报文的返回地址. 2)目的端口:端口指明接收方计算机上的应用程序接口. TCP报头中的源端口 ...
- Linux中soft nproc 、soft nofile和hard nproc以及hard nofile配置
Linux中soft nproc .soft nofile和hard nproc以及hard nofile配置 "soft" 和 "hard" 的区别 soft ...
- vscode 设置 eclipse 快捷键
点击安装之后,默认就是要ecliplse快捷键了 注意:部分快捷键可能会由于和原来的冲突而失效,例如快速在“下面插入行” ,我还是不能使用ecliplse的Shift+Enter,而要用Ctrl+En ...
- LC 794. Valid Tic-Tac-Toe State
A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to r ...