hdu5909:Tree Cutting (FWT/点分治优化树形DP)
2018-03-15 21:33
363 查看
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5909
题目大意:给出一棵树,每个节点的权值都在[0,m)[0,m)内。现在对于每个v∈[0,m)v∈[0,m),你都应给出权值为vv的至少有一个点的子连通块个数。一个连通块的权值定义为其所有点的权值异或和。答案模109+7109+7,多组数据。
题目分析:首先很容易想到O(Tnm2)O(Tnm2)的树形DP。由于树的一个子连通块也是一棵树,可以使1号点为整棵树的根,定义子连通块的根为其中深度最小的节点。然后令f[node][v]表示以node为根,异或和为v的子连通块有多少个。显然,当逐个考虑node的儿子的时候,考虑新的儿子son对f[node][v]的贡献,发现有以下形式的转移:
f[node][v]=∑t=0m−1f[node][t]∗f[son][v⊕t]f[node][v]=∑t=
12561
0m−1f[node][t]∗f[son][v⊕t]
其中⊕⊕是异或操作。
这个方程显然可以用FWT优化,这样O(Tnmlog(m))O(Tnmlog(m))就可以通过所有数据。然而这样常数很大,方法也不够巧妙,有没有别的优化方法呢?
我们发现本题是询问关于树上的连通块问题,因为不知道连通块的根,所以要对每个节点DP。假设强制这个连通块过根,能不能降低DP的时间复杂度呢?我们又发现:如果这个连通块过根,那么若一个点不选,它的子树也不能选;否则它的子树才有可能选。如果定义一个指针指向当前考虑的节点的话,那么前者就表示这个指针移向了DFS序上该子树对应区间的右一位,而后者就代表指针直接移向DFS序的下一位。这样按DFS序去DP,时间就是O(nm)O(nm)的。
那么如何处理不过根的问题呢?只要套个点分治就行了。这样总时间复杂度是O(Tnmlog(n))O(Tnmlog(n))的,不仅方法优美而且十分好写。
CODE:
题目大意:给出一棵树,每个节点的权值都在[0,m)[0,m)内。现在对于每个v∈[0,m)v∈[0,m),你都应给出权值为vv的至少有一个点的子连通块个数。一个连通块的权值定义为其所有点的权值异或和。答案模109+7109+7,多组数据。
题目分析:首先很容易想到O(Tnm2)O(Tnm2)的树形DP。由于树的一个子连通块也是一棵树,可以使1号点为整棵树的根,定义子连通块的根为其中深度最小的节点。然后令f[node][v]表示以node为根,异或和为v的子连通块有多少个。显然,当逐个考虑node的儿子的时候,考虑新的儿子son对f[node][v]的贡献,发现有以下形式的转移:
f[node][v]=∑t=0m−1f[node][t]∗f[son][v⊕t]f[node][v]=∑t=
12561
0m−1f[node][t]∗f[son][v⊕t]
其中⊕⊕是异或操作。
这个方程显然可以用FWT优化,这样O(Tnmlog(m))O(Tnmlog(m))就可以通过所有数据。然而这样常数很大,方法也不够巧妙,有没有别的优化方法呢?
我们发现本题是询问关于树上的连通块问题,因为不知道连通块的根,所以要对每个节点DP。假设强制这个连通块过根,能不能降低DP的时间复杂度呢?我们又发现:如果这个连通块过根,那么若一个点不选,它的子树也不能选;否则它的子树才有可能选。如果定义一个指针指向当前考虑的节点的话,那么前者就表示这个指针移向了DFS序上该子树对应区间的右一位,而后者就代表指针直接移向DFS序的下一位。这样按DFS序去DP,时间就是O(nm)O(nm)的。
那么如何处理不过根的问题呢?只要套个点分治就行了。这样总时间复杂度是O(Tnmlog(n))O(Tnmlog(n))的,不仅方法优美而且十分好写。
CODE:
#include<iostream> #include<string> #include<cstring> #include<cmath> #include<cstdio> #include<cstdlib> #include<stdio.h> #include<algorithm> using namespace std; const int maxn=1050; const long long M=1000000007; typedef long long LL; struct edge { int obj; edge *Next; } e[maxn<<1]; edge *head[maxn]; int cur; int tree[maxn]; int num; int Size[maxn]; int max_Size[maxn]; int dfsx[maxn]; int st[maxn]; int ed[maxn]; LL f[maxn][maxn]; LL ans[maxn]; int val[maxn]; bool vis[maxn]; int t,n,m; void Add(int x,int y) { cur++; e[cur].obj=y; e[cur].Next=head[x]; head[x]=e+cur; } void Dfs1(int node,int fa) { num++; tree[num]=node; Size[node]=1; max_Size[node]=0; for (edge *p=head[node]; p; p=p->Next) { int son=p->obj; if ( son==fa || vis[son] ) continue; Dfs1(son,node); Size[node]+=Size[son]; max_Size[node]=max(max_Size[node],Size[son]); } } void Dfs2(int node,int fa) { num++; dfsx[num]=node; st[node]=num; for (edge *p=head[node]; p; p=p->Next) { int son=p->obj; if ( son==fa || vis[son] ) continue; Dfs2(son,node); } ed[node]=num; } void Solve(int node) { num=0; Dfs1(node,node); if (num==1) { ans[ val[node] ]=(ans[ val[node] ]+1)%M; return; } int root=tree[1]; for (int i=1; i<=num; i++) { int x=tree[i]; Size[x]=max(Size[node]-Size[x],max_Size[x]); if (Size[x]<Size[root]) root=x; } num=0; Dfs2(root,root); for (int i=2; i<=num+1; i++) for (int j=0; j<m; j++) f[i][j]=0; f[2][ val[ dfsx[1] ] ]=1; for (int i=2; i<=num; i++) for (int j=0; j<m; j++) { LL &x=f[i+1][ j^val[ dfsx[i] ] ]; x=(x+f[i][j])%M; LL &y=f[ ed[ dfsx[i] ]+1 ][j]; y=(y+f[i][j])%M; } for (int i=0; i<m; i++) ans[i]=(ans[i]+f[num+1][i])%M; vis[root]=true; for (edge *p=head[root]; p; p=p->Next) { int son=p->obj; if (vis[son]) continue; Solve(son); } } int main() { freopen("5909.in","r",stdin); freopen("5909.out","w",stdout); scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) head[i]=NULL,vis[i]=false,scanf("%d",&val[i]); cur=-1; for (int i=1; i<n; i++) { int x,y; scanf("%d%d",&x,&y); Add(x,y); Add(y,x); } for (int i=0; i<m; i++) ans[i]=0; Solve(1); for (int i=0; i<m-1; i++) printf("%d ",ans[i]); printf("%d\n",ans[m-1]); } return 0; }
相关文章推荐
- HDU - 5909 Tree Cutting 树形DP+fwt优化 或点分治(待补)
- POJ 1741 Tree 树形DP(分治)
- JZOJ 5496 Tree(点分治+树形dp)
- dp优化专辑 I - Cut the Tree [树形dp]
- [codeforces161D]Distance in Tree(点分治/树形dp)
- [树形DP] [FWT] [HDU5909] Tree Cutting
- POJ 1741 Tree 树形DP(分治)
- *POJ 1741 - Tree(树形DP‘树的分治)
- HDU 5909 Tree Cutting (点分治+树形DP|FWT+树形DP)
- HDOJ树形DP专题之Tree Cutting
- BZOJ1492 货币兑换 CDQ分治优化DP
- ZOJ3201 Tree of Tree 【树形dp】
- Hdu-5834 Magic boy Bi Luo with his excited tree(树形DP)
- SRM12 T2夏令营(分治优化DP+主席树 (已更新NKlogN)/ 线段树优化DP)
- hdu 5834 Magic boy Bi Luo with his excited tree 树形dp
- zoj3951 Independent Set(树形dp,空间优化)
- BestCoder #65 1004 ZYB'S Tree(树形DP)
- pku1848 Tree 树形DP
- 【Codeforces Round 263 (Div 2)D】【树形DP】Appleman and Tree 树上割k个黑点为k块的方案数
- HDU 6161 树形DP + 优化