hdu5416
通过这道题来看,异或或许和最近公共祖先之间有着某种关系。最近公共祖先,是(1,n),(1,v)去掉相同的部分,而异或也是异或两次相当于没有异或。剩下的就好说了,纯暴力。本来以为会超时,但是竟然过了,以前以为不会超时的题,竟然超时了,所以说学好时间复杂度很重要。至于N的选值要注意。还有最后ans的处理上,也要注意,有些点对会出现两次,但是有的只出现一次。所以要进行处理后在除以2。一直wr在了ans的处理上,看了别人的代码受到启发。
代码参考:http://blog.csdn.net/DoJintian/article/details/47834933
2015.8.29:
hahaha到此一游
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 262200
int dp[N];
long long int numcou[N];
int head[N],to[2*N],nextedge[2*N],w[2*N];
int cou;
void add(int a,int b,int c){
to[cou]=b;w[cou]=c;nextedge[cou]=head[a];head[a]=cou++;//printf("wo shi da hao ren");
//printf("%d %d %d %d\n",a,b,c,cou);
}
void dfs(int u,int fa){
numcou[dp[u]]++;
//printf("%d %dha\n",u,head[u]);
for(int i=head[u];i!=-1;i=nextedge[i]){
int v=to[i];
if(v==fa){
continue;
}
else{
dp[v]=w[i]^dp[u];
//printf("%d %d %d\n",u,v,w[i]);
dfs(v,u);
}
}
return;
}
int main(){
int t;
int n;
int q;
int a,b,c;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
cou=0;
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
memset(numcou,0,sizeof(numcou));
dp[1]=0;
dfs(1,-1);
/*for(int i=1;i<=n;i++){
printf("%d ",dp[i]);
}*/
scanf("%d",&q);
for(int i=0;i<q;i++){
scanf("%d",&a);
long long int ans=0;
for(int i=0;i<N;i++){
int temp=a^i;
ans=ans+numcou[temp]*numcou[i];
}
if(!a){
ans=ans+n;
}
printf("%lld\n",ans/2);
}
}
return 0;
}

浙公网安备 33010602011771号