题意:给一个树和树上的边权,然后Q个询问,每次询问树上的不同点对的路径异或值为s
思路:因为a^b==c则a^c==b,所以我们以1为根建树,然后每个节点保存1到自己的异或值,然后每一个异或值都记录个数,最后询问的时候就遍历所有的点为结尾,然后看一下有多少个出现过,但是会算两遍,然后就是注意s==0的情况
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int num[2*maxn],vis[maxn],dis[maxn],kkk,head[maxn];
struct node{
int to,next,cost;
}EE[2*maxn];
void add_edge(int u,int v,int cost){
EE[kkk].to=v;EE[kkk].cost=cost;EE[kkk].next=head[u];head[u]=kkk++;
}
void dfs(int u,int fa,int ddd){
num[ddd]++;dis[u]=ddd;
for(int i=head[u];i!=-1;i=EE[i].next){
int v=EE[i].to;
if(v==fa) continue;
int lll=ddd^EE[i].cost;
dfs(v,u,lll);
}
}
int main(){
int T,n,u,v,c,q;
scanf("%d",&T);
while(T--){
scanf("%d",&n);kkk=0;
memset(head,-1,sizeof(head));
memset(num,0,sizeof(num));
for(int i=0;i<n-1;i++){
scanf("%d%d%d",&u,&v,&c);
add_edge(u,v,c);
add_edge(v,u,c);
}
dfs(1,0,0);
scanf("%d",&q);
while(q--){
scanf("%d",&u);
ll ans=0;
for(int i=1;i<=n;i++){
int ttt=u^dis[i];
if(u==0) ans+=(num[ttt]-1);
else ans+=num[ttt];
}
if(u==0) ans+=2*n;
printf("%I64d\n",ans/2);
}
}
return 0;
}