题意:给出一棵树,和树边的权值,q个询问,每次给出s求有多少条路径上边权值异或值为s。
由于可得f(u,v) = f(1,u)\ f(1, u) f(1,u) ^f(1,v) f(1, v)f(1,v), 那么就离线处理出以1为树根的树xor前缀,并hash记录该异或值数量,对于每个询问s,遍历1~n,累计num【xor【i】】即可,注意s = 0时,所有的值1~n都满足(x^x = 0),要多加一个n,最后结果/2
#include <bits/stdc++.h>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <time.h>
#include <vector>
#include <cstdio>
#include <string>
#include <iomanip>
///cout << fixed << setprecision(13) << (double) x << endl;
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
#define Mp(a, b) make_pair(a, b)
#define asd puts("asdasdasdasdasdf");
typedef long long ll;
typedef pair <int, int> pl;
//typedef __int64 LL;
const int inf = 0x3f3f3f3f;
const int N = 100010;
ll xr[N];
int head[N];
int n, cnt, q;
ll num[N*20];
struct node{
int v, w, nxt;
}e[N<<1];
void init()
{
cnt = 0;
memset( num, 0, sizeof( num ) );
memset( head, -1, sizeof( head ) );
memset( xr, 0, sizeof( xr ) );
}
void add( int u, int v, int w )
{
e[cnt].v = v;
e[cnt].w = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
e[cnt].v = u;
e[cnt].w = w;
e[cnt].nxt = head[v];
head[v] = cnt++;
}
void dfs( int u, int fa )
{
for( int i = head[u]; ~i; i = e[i].nxt ) {
int v = e[i].v, w = e[i].w;
if( v == fa )
continue;
xr[v] = xr[u] ^ w;
dfs( v, u );
}
}
int main()
{
int tot;
scanf("%d", &tot);
while( tot-- ) {
scanf("%d", &n);
init();
for( int i = 1, u, v, w; i < n; ++i ) {
scanf("%d%d%d", &u, &v, &w);
add( u, v, w );
}
dfs( 1, -1 );
for( int i = 1; i <= n; ++i )
num[ xr[i] ]++;
scanf("%d", &q);
while( q-- ) {
ll ans = 0, zero = 0;
ll tmp;
scanf("%lld", &tmp);
for( int i = 1; i <= n; ++i ) {
ll x = tmp ^ xr[i];
ans += num[x];
if( tmp == 0 )
zero = 1;
}
ans += zero * n;
printf("%lld\n", ans/2);
}
}
return 0;
}