题意:给一颗树,定义f(u,v)为u到v路径上的异或结果,现在给定s,要求异或结果为s的路径有多少条。(1,2)和(2,1)只算一种。
根据异或的特性有f(u,v)=f(1,u)f(1,v),先把f(1,i)的所有i都求出,然后对于每一个u(1~n)如果有f(u,v)=s的话那么有f(1,v)=sf(1,u),所以求一下f(1,v)有多少个,加起来就行了,最后要特殊讨论下s==0的情况。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> #include <limits> using namespace std; typedef long long LL; const int MAXN=100000*2+1000; const int INF = numeric_limits<int>::max(); const LL LL_INF= numeric_limits<LL>::max(); struct Edge { int to,next,w; Edge(){} Edge(int _to,int _next,int _w):to(_to),next(_next),w(_w){} }e[MAXN<<1]; int head[MAXN],tot; void init(){ memset(head,-1,sizeof(head)); tot=0; } void AddEdge(int u,int v,int w){ e[tot]=Edge(v,head[u],w); head[u]=tot++; e[tot]=Edge(u,head[v],w); head[v]=tot++; } int dis[MAXN]; int has[1<<17],N,Q,T; void dfs(int u,int fa){ ++has[dis[u]]; for(int i=head[u];~i;i=e[i].next){ int v=e[i].to; if(v==fa)continue; if(dis[v]!=-1)continue; dis[v]=dis[u]^e[i].w; dfs(v,u); } } int main() { scanf("%d",&T); while(T--){ scanf("%d",&N); init(); for(int i=0,x,y,w;i<N-1;i++){ scanf("%d%d%d",&x,&y,&w); AddEdge(x,y,w); } memset(has,0,sizeof(has)); memset(dis,-1,sizeof(dis)); dis[1]=0; dfs(1,-1); scanf("%d",&Q); LL ans=0; int s; while(Q--){ scanf("%d",&s); ans=0; for(int i=1;i<=N;i++)ans+=has[s^dis[i]]; if(!s)ans+=N; ans/=2; printf("%I64d\n",ans); } } return 0; }
|