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; }