HDU 5909 Tree Cutting 【树型DP】


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,bin)

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




猜你喜欢

转载自blog.csdn.net/my_sunshine26/article/details/79992142