首先预处理出来所有节点到根节点的异或值,然后对于节点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; }