标签:
//给一棵树
//对任意的s
//问有多少对(u,v)是的从u到v的路径的所有边权值为s
//f(u,v) = f(root , u)^f(root ,v)
//只要记录所有点到树根的路径的异或值
//然后枚举端点
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 1e5+10 ;
typedef long long ll ;
int nedge ;
int vis[maxn] ;
int Hash[maxn<<1] ;
int dp[maxn] ;
struct Edge
{
int v ;int w ;
int next ;
}edge[maxn<<1] ;
int head[maxn] ;
void addedge(int u , int v , int w)
{
edge[nedge].v = v ;
edge[nedge].w = w ;
edge[nedge].next = head[u] ;
head[u] = nedge++ ;
}
void dfs(int u , int sum ,int pre)
{
for(int i = head[u] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].v ;
if(v == pre)continue ;
dp[v] = sum^edge[i].w ;
Hash[dp[v]]++ ;
dfs(v , dp[v] , u ) ;
}
}
int main()
{
//freopen("in.txt" , "r" , stdin ) ;
int n ;
int t ;
scanf("%d" , &t) ;
while(t--)
{
memset(vis , 0 , sizeof(vis)) ;
memset(Hash , 0 , sizeof(Hash)) ;
memset(head , -1 , sizeof(head)) ;
nedge = 0 ;
scanf("%d" , &n) ;
for(int i = 1;i < n;i++)
{
int u , v , w ;
scanf("%d%d%d" , &u , &v , &w) ;
addedge(u , v , w) ;
addedge(v , u , w) ;
vis[v] = 1 ;
}
Hash[0] = 1 ;
dp[1] = 0 ;
dfs(1 , 0 , -1) ;
int q ;
scanf("%d" , &q) ;
while(q--)
{
int s ;
scanf("%d" , &s) ;
ll ans = 0 ;
for(int i = 1;i <= n;i++)
{
int tmp = dp[i]^s ;
ans += (ll)Hash[tmp] ;
}
if(s)
cout<<ans/2<<endl ;
else
cout<<(ans+(ll)n)/2<<endl;
}
}
return 0 ;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/cq_pf/article/details/48109773