hdu 5909 Tree Cutting(树形dp+树上点分治)

Tree Cutting

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Others)
Total Submission(s): 1291    Accepted Submission(s): 498


 

Problem Description

Byteasar has a tree T with n vertices conveniently labeled with 1,2,...,n. Each vertex of the tree has an 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 input contains 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 tree T 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 each node.

Each of the following n−1 lines contains two integers ai,bi, denoting an edge between vertices 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 a line with m integers, the i-th number denotes the number of non-empty subtree of T which value are equal to i.

The answer is huge, so please module 109+7.


#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1050;
const ll mod=1e9+7;
vector<int>G[maxn];
int n,m,a[maxn];
int root,now_size,son[maxn];
int ans[maxn],dp[2*maxn][2*maxn];
bool vis[maxn];
void get_root(int v,int fa,int SIZE)
{
    son[v]=1;
    int ma=0;
    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==fa||vis[to]) continue;
        get_root(to,v,SIZE);
        son[v]+=son[to];
        ma=max(ma,son[to]);
    }
    ma=max(ma,SIZE-son[v]);
    if(ma<now_size)
    {
        now_size=ma;
        root=v;
    }
}
void get_ans(int v,int fa)
{

    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==fa||vis[to]) continue;
        for(int j=0;j<m;j++) dp[to][j]=0;
        for(int j=0;j<m;j++) dp[to][a[to]^j]=(dp[to][a[to]^j]+dp[v][j])%mod;
        get_ans(to,v);
        for(int j=0;j<m;j++) dp[v][j]=(dp[v][j]+dp[to][j])%mod;
    }
}
void dfs(int v,int fa)
{
    vis[v]=1;
    for(int i=0;i<m;i++) dp[v][i]=0;
    dp[v][a[v]]=1;
    get_ans(v,fa);
    for(int i=0;i<m;i++) (ans[i]+=dp[v][i])%=mod;
    for(int i=0;i<G[v].size();i++)
    {
        int to=G[v][i];
        if(to==fa||vis[to]) continue;
        now_size=1e9;
        get_root(root=to,v,now_size=son[to]);
        dfs(root,v);
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        for(int i=0;i<maxn;i++) G[i].clear();
        memset(ans,0,sizeof(ans));
        memset(vis,0,sizeof(vis));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<n;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        get_root(root=1,0,now_size=n);
        dfs(root,0);
        for(int i=0;i<m;i++)
        {
            printf("%d",ans[i]);
            if(i<m-1) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/albertluf/article/details/81435787