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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章