Tree Cutting
Time Limit: 4000/2000 MS(Java/Others) Memory Limit: 262144/131072 K(Java/Others)
Total Submission(s): 1048 Accepted Submission(s): 422
Problem Description
Byteasar has a tree T with n vertices conveniently labeledwith 1,2,...,n. Each vertex of the tree hasan integer value vi.
The value of a non-empty tree T is equal to v1⊕v2⊕...⊕vn, where ⊕denotes bitwise-xor.
Now for every integer k from [0,m), please calculate the number of non-empty subtree of T which value are equal to k
A subtree of T is a subgraph of T that is also a tree.
Input
The first line of the inputcontains an integer T(1≤T≤10) denoting the number of test cases.
In each test case, the first line of the input contains two integers n(n≤1000) and m(1≤m≤210) denoting the size of the treeT and the upper-bound of v.
The second line of the input contains n integers v1,v2,v3,...,vn(0≤vi<m), denoting the value of eachnode.
Each of the following n−1 lines contains two integers ai,bi, denoting an edge betweenvertices ai and bi(1≤ai,bi≤n)
It is guaranteed that m can be represent as 2k, where k is a non-negative integer.
Output
For each test case, print aline with m integers, the i th number denotes the numberof non-empty subtree of T which value are equal to i.
The answer is huge, so please module 109+7.
Sample Input
2
4 4
2 0 1 3
1 2
1 3
1 4
4 4
0 1 3 1
1 2
1 3
1 4
Sample Output
3 3 2 3
2 4 2 3
【题目链接】 link
【题意】
已知一棵树的值为该树上所有节点的异或值,现在给你一颗树,问该树的所有子树的值在[0,m)各出现了几次。
【思路】
用vis[i][j]表示以i为根的树中j这个异或值有没有出现过
用val[i][j]表示以i为根的树的第j个异或值
用sz[i]表示以i为根的树不同异或值的个数
用dp[i][j]表示以i为根的树异或值为j的个数
然后就用dfs从树的叶子节点往上更新即可
#include <cstdio>
#include <bits/stdc++.h>
#include <cmath>
#include <map>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 1500;
const ll mod = 1e9+7;
const int INF = 1e9;
const double eps = 1e-6;
int n,m,cnt;
ll a[maxn];
int head[maxn];
int vis[maxn][maxn];
ll dp[maxn][maxn];
ll val[maxn][maxn];
int sz[maxn];
ll tmp[maxn];
struct node
{
int v,next;
}e[maxn*2];
void add(int u,int v)
{
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int u,int pre)
{
val[u][sz[u]++]=a[u];
vis[u][a[u]]=1;
dp[u][a[u]]=1;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(v==pre) continue;
dfs(v,u);
mst(tmp,0);
for(int j=sz[u]-1;j>=0;j--)
for(int k=0;k<sz[v];k++)
{
ll x=val[u][j],y=val[v][k];
tmp[x^y]+=(dp[u][x]*dp[v][y])%mod;
if(vis[u][x^y]==0)
{
val[u][sz[u]++]=x^y;
vis[u][x^y]=1;
}
}
for(int j=0;j<m;j++)
{
dp[u][j]+=tmp[j];
dp[u][j]%=mod;
}
}
}
int main()
{
rush()
{
scanf("%d%d",&n,&m);
mst(head,-1);
cnt=0;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
mst(sz,0);
mst(vis,0);
mst(dp,0);
dfs(1,-1);
for(int i=0;i<m;i++)
{
ll ans=0;
for(int j=1;j<=n;j++) ans=(ans+dp[j][i])%mod;
printf("%lld",ans);
if(i==m-1) puts("");
else printf(" ");
}
}
}