hdu5909-Tree Cutting(树形dp)

时间:2022-10-26 00:11:38

偷偷抄bestcoser上面hnust_zhaozhixuan的代码 = = 因为题解看不懂阿

#include <cstdio>
#include <cstring> typedef long long ll; using namespace std;
const int N = ;
const int MOD = 1e9 + ; int Scan() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = (x << ) + (x << ) + ch - ''; ch = getchar(); }
return x * f;
} struct Edge {
int to, next;
} edge[N*];
int head[N], cntE;
void addedge(int u, int v) {
edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
edge[cntE].to = u; edge[cntE].next = head[v]; head[v] = cntE++;
}
int a[N], n, m; int sz[N]; // sz[u] 记录 根为 u 点 有多少个异或值
int val[N][N]; // val[u][i] 记录 u 点 第 i 个的异或值都是什么
int dp[N][N]; // dp[u][i] 记录 根为 u 点 异或值为i的数量
int vis[N][N]; // vis[i] 记录 i 这个 异或值是否出现过
int tmp[N]; void add(int &a, int b) {
a = ((ll)a + b) % MOD;
} void dfs(int u, int fa) {
dp[u][ a[u] ] = ;
val[u][ sz[u]++ ] = a[u];
vis[u][ a[u] ] = true;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
dfs(v, u);
memset(tmp, , sizeof(int)*m);
for (int j = sz[u]-; j >= ; --j) {
for (int k = ; k < sz[v]; ++k) {
int a = val[u][j], b = val[v][k];
add(tmp[a^b], (ll)dp[u][a] * dp[v][b] % MOD);
if (!vis[u][a^b]) val[u][sz[u]++] = a^b, vis[u][a^b] = true;
}
}
for (int j = ; j < m; ++j) add(dp[u][j], tmp[j]);
}
} void init() {
memset(head, -, sizeof(int)*(n+));
memset(sz, , sizeof(int)*(n+));
for (int i = ; i <= n; ++i)
memset(dp[i], , sizeof(int)*m), memset(vis[i], , sizeof(int)*m);
cntE = ;
} int main()
{
//freopen("in.txt", "r", stdin);
int T = Scan();
while (T--) {
n = Scan(), m = Scan();
init();
for (int i = ; i <= n; ++i) a[i] = Scan();
for (int i = ; i < n; ++i) addedge(Scan(), Scan());
dfs(, ); for (int k = ; k < m; ++k) {
int ans = ;
for (int i = ; i <= n; ++i) add(ans, dp[i][k]);
printf("%d%c", ans, k==m-?'\n':' ');
} }
return ;
}