题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909

点分治的话,每次要做一次树形DP;但时间应该是 siz*m2 的。可以用 FWT 变成 siz*mlogm ,但这里写的是把树变成序列来 DP 的方法,应该是 nlogn*m 的。

树上的一个点,如果选,就可以选它的孩子,所以它向它的第一个孩子连边;如果不选,就会跳到它的下一个兄弟或者是父亲的下一个兄弟之类的,向那边连一条边。

做出树的 dfs 序,把边都连在 dfs 序上;其实那个第一条边一定连向自己 dfs 序+1,即使自己没有孩子也是符合的,所以可以不用连了;第二条边可以通过传父亲的连边对象来解决。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,M=,mod=1e9+;
int T,n,m,w[N],hd[N],xnt,to[N<<],nxt[N<<],siz[N],rt,mn;
int dfn[N],tot,sta[N],top,f[N][M],g[N],nt[N],ans[M]; bool vis[N];
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
void upd(int &x){x>=mod?x-=mod:;}
void init()
{
xnt=;memset(hd,,sizeof hd);
memset(ans,,sizeof ans); memset(vis,,sizeof vis);
}
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void getrt(int cr,int fa,int s)
{
siz[cr]=; int mx=;
for(int i=hd[cr],v;i;i=nxt[i])
if(!vis[v=to[i]]&&v!=fa)
{
getrt(v,cr,s);siz[cr]+=siz[v];
mx=Mx(mx,siz[v]);
}
mx=Mx(mx,s-siz[cr]);if(mx<mn)mn=mx,rt=cr;
}
void dfs(int cr,int fa)
{
dfn[cr]=++tot;g[tot]=w[cr];
for(int i=hd[cr],v;i;i=nxt[i])
if(!vis[v=to[i]]&&v!=fa)dfs(v,cr);
}
void dfsx(int cr,int fa,int lst)
{
nt[dfn[cr]]=lst;
int l=top+;
for(int i=hd[cr],v;i;i=nxt[i])
if(!vis[v=to[i]]&&v!=fa)sta[++top]=v;
int r=top;
for(int i=hd[cr],v,p0=l;i;i=nxt[i])
if(!vis[v=to[i]]&&v!=fa)
{
dfsx(v,cr,p0==r?lst:dfn[sta[p0+]]);p0++;
}
}
void solve(int cr,int s)
{
vis[cr]=;
tot=;dfs(cr,);top=;dfsx(cr,,s+);
for(int i=;i<=s+;i++)memset(f[i],,sizeof f[i]);
f[][]=;
for(int i=;i<=s;i++)
for(int j=;j<m;j++)
{
if(!f[i][j])continue;
f[i+][j^g[i]]+=f[i][j];upd(f[i+][j^g[i]]);
f[nt[i]][j]+=f[i][j];upd(f[nt[i]][j]);
}
f[s+][]--;//dec the empty
for(int j=,k=s+;j<m;j++)ans[j]+=f[k][j],upd(ans[j]);
for(int i=hd[cr],v,ts;i;i=nxt[i])
if(!vis[v=to[i]])
{
ts=(siz[cr]>siz[v]?siz[v]:s-siz[cr]);
mn=N;getrt(v,cr,ts);solve(rt,ts);
}
}
int main()
{
T=rdn();
while(T--)
{
n=rdn();m=rdn();for(int i=;i<=n;i++)w[i]=rdn();
init();
for(int i=,u,v;i<n;i++)u=rdn(),v=rdn(),add(u,v),add(v,u);
mn=N;getrt(,,n);solve(rt,n);
for(int i=,j=m-;i<j;i++)printf("%d ",ans[i]);
printf("%d\n",ans[m-]);
}
return ;
}

hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)的更多相关文章

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

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

  2. hdu 5909 Tree Cutting —— 点分治

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

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

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

  4. HDU - 5909 Tree Cutting (树形dp+FWT优化)

    题意:树上每个节点有权值,定义一棵树的权值为所有节点权值异或的值.求一棵树中,连通子树值为[0,m)的个数. 分析: 设\(dp[i][j]\)为根为i,值为j的子树的个数. 则\(dp[i][j\o ...

  5. HDU 5909 Tree Cutting 动态规划 快速沃尔什变换

    Tree Cutting 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5909 Description Byteasar has a tree T ...

  6. HDU.5909.Tree Cutting(树形DP FWT/点分治)

    题目链接 \(Description\) 给定一棵树,每个点有权值,在\([0,m-1]\)之间.求异或和为\(0,1,...,m-1\)的非空连通块各有多少个. \(n\leq 1000,m\leq ...

  7. HDU 5909 Tree Cutting

    传送门 题意: 有一棵n个点的无根树,节点依次编号为1到n,其中节点i的权值为vi, 定义一棵树的价值为它所有点的权值的异或和. 现在对于每个[0,m)的整数k,请统计有多少T的非空连通子树的价值等于 ...

  8. hdoj5909 Tree Cutting(点分治+树上dp转序列dp)

    题目链接:https://vjudge.net/problem/HDU-5909 题意:给一颗树,结点带权值v[i]<m.求异或和为k的子树个数(0<=k<m). 思路: 首先点分治 ...

  9. E. Alternating Tree 树点分治|树形DP

    题意:给你一颗树,然后这颗树有n*n条路径,a->b和b->a算是一条,然后路径的权值是 vi*(-1)^(i+1)  注意是点有权值. 从上头往下考虑是点分治,从下向上考虑就是树形DP, ...

随机推荐

  1. JavaScript进阶内容笔记1:各种对象类型判断

    该文章主要用来介绍JavaScript中常用的一些对象检测判断方法,整理资源来自书本和网络,如有错误或说明不详之处,望评论提出,本菜定提名感谢……(本文章知识比较基础,大牛请提些意见再绕道,三克油^_ ...

  2. remount issue on android 7.0

    http://blog.chinaunix.net/uid-23141914-id-5754416.html 最近在新版本的android 7.0上,发现filesystem的remount老是报“  ...

  3. 搞定PHP面试 - 正则表达式知识点整理

    一.简介 1. 什么是正则表达式 正则表达式(Regular Expression)就是用某种模式去匹配一类字符串的一种公式.正则表达式使用单个字符串来描述.匹配一系列匹配某个句法规则的字符串.正则表 ...

  4. 20135320赵瀚青LINUX期中总结

    期中总结 心得与体会 本学期的LINUX内核这门课程已经进行了一半,这门课的学习方法和上个学期深入理解计算机系统的方式差不多,所以也没有特别多不适应,LINUX内核在我看来,就是理解一个操作系统是如何 ...

  5. Kali视频学习16-20

    Kali视频学习16-20 (16)Kali漏洞分析之数据库评估(一) 一. BBQSql BBQSql 是Python编写的盲注工具(blind SQL injection framework),当 ...

  6. 20172305 2018-2019-1 《Java软件结构与数据结构》第三周学习总结

    20172305 2018-2019-1 <Java软件结构与数据结构>第三周学习总结 教材学习内容总结 本周内容主要为书第五章内容: 队列 线性集合(元素从一端加入,另一端删除) 先进先 ...

  7. 【P4语言学习】Parser解析器

    参考文章:王垠:谈谈Parser 簡單介紹 P4 語言(一)- Parser 什么是Parser 传统的parser,一般出现在编译器和编译原理课程中,援引<谈谈Parser>的定义: 首 ...

  8. 【转载】linux fork死循环炸弹及其预防

    转自linux fork死循环炸弹及其预防 在Linux系统下执行这段代码 :(){ :|:& }:: 就会引起死机,一旦执行起来后,唯一的方法就是重启系统.实际上这段代码是一段无限递归代码, ...

  9. POJ 2528 Mayor's posters(线段树染色问题+离散化)

    http://poj.org/problem?id=2528 题意: 给出一面无限长的墙,现在往墙上依次贴海报,问最后还能看见多少张海报. 题意:这道题目就相当于对x轴染色,然后计算出最后还能看见多少 ...

  10. pycharm中查看快速帮助和python官方帮助文档

    把光标放在要查询的对象上,打开视图菜单,quick definition查看对象的定义,quick documentation 快速文档,这个是jet brains自己对python的解释文档,第三个 ...