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


posted @ 2015-08-25 09:56  buzhidaohahaha  阅读(140)  评论(0编辑  收藏  举报