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(" ");
}
}
}