首先预处理出来所有节点到根节点的异或值,然后对于节点u,v,f(u,v)=f(u,1)^f(v,1)(由于异或的性质)
然后我们可以对于每个询问s,枚举所有的v,对于每一个v查找有几个u,使得s^f(v,1)=f(u,1)
至于查找u的时候,我们可以先预处理出来所有的f(u,1)的取值的个数,就是cnt[f(u,1)],然后直接访问cnt[s^f(v,1)]就成了。
特别注意s=0,u=v时候要特殊处理一下
#pragma warning(disable:4996)
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
vector<int>g[N], e[N];
int a[N], cnt[N * 10];
bool vis[N];
void init(){
for (int i = 0; i < N; i++){
g[i].clear();
e[i].clear();
}
memset(a, 0, sizeof a);
memset(cnt, 0, sizeof cnt);
memset(vis, false, sizeof vis);
}
void add(int u, int v, int c){
g[u].push_back(v);
e[u].push_back(c);
}
void bfs(int u){
queue<int>q;
q.push(u);
a[u] = 0;
vis[u] = true;
while (!q.empty()){
u = q.front(); q.pop();
for (int i = 0; i < g[u].size(); i++){
int v = g[u][i], c = e[u][i];
if (!vis[v]){
q.push(v);
a[v] = a[u] ^ c;
vis[v] = true;
}
}
}
}
void dfs(int u, int val){
vis[u] = true;
a[u] = val;
for (int i = 0; i < g[u].size(); i++){
int v = g[u][i], c = e[u][i];
if (!vis[v]){
dfs(v, val^c);
}
}
}
int main(){
//freopen("in.txt", "r", stdin);
int t; scanf("%d", &t);
while (t--){
init();
int n; scanf("%d", &n);
for (int i = 1; i < n; i++){
int u, v, c;
scanf("%d %d %d", &u, &v, &c);
add(u, v, c);
add(v, u, c);
}
//dfs(1, 0);
bfs(1);
for (int i = 1; i <= n; i++)cnt[a[i]]++;
int q; scanf("%d", &q);
while (q--){
int x; scanf("%d", &x);
long long ans = 0;
for (int i = 1; i <= n; i++){
ans = ans + (long long)cnt[a[i] ^ x];
}
if (x)ans /= 2;
if (x == 0){
ans -= (long long)n;
ans /= 2;
ans += (long long)n;
}
printf("%lld\n", ans);
}
}
return 0;
}