CRB and Tree(树形+异或性质)

CRB and Tree

http://acm.hdu.edu.cn/showproblem.php?pid=5416

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2411    Accepted Submission(s): 730


 

Problem Description

CRB has a tree, whose vertices are labeled by 1, 2, …, N. They are connected by N – 1 edges. Each edge has a weight.
For any two vertices u and v(possibly equal), f(u,v) is xor(exclusive-or) sum of weights of all edges on the path from u to v.
CRB’s task is for given s, to calculate the number of unordered pairs (u,v) such that f(u,v) = s. Can you help him?

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer N denoting the number of vertices.
Each of the next N - 1 lines contains three space separated integers a, b and c denoting an edge between a and b, whose weight is c.
The next line contains an integer Q denoting the number of queries.
Each of the next Q lines contains a single integer s.
1 ≤ T ≤ 25
1 ≤ N ≤ 105
1 ≤ Q ≤ 10
1 ≤ a, bN
0 ≤ c, s ≤ 105
It is guaranteed that given edges form a tree.

Output

For each query, output one line containing the answer.

Sample Input

1
3
1 2 1
2 3 2
5
2
3
4
0
0

Sample Output

1

1

0

Hint

For the first query, (2, 3) is the only pair that f(u, v) = 2. For the second query, (1, 3) is the only one. For the third query, there are no pair (u, v) such that f(u, v) = 4.

Author

KUT(DPRK)

Source

2015 Multi-University Training Contest 10

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6408 6407 6406 6405 6404 

思路:这道题要用到异或的性质。就是j^k^j还是k

用lala[i]来表示根节点到i节点的异或值。(这里只有边权)然后就是两点之间的异或值就是lala[u]^lala[v]了。

还要用一下cnt【i】来表示从根节点到当前节点的异或值为i的有几个。

然后每一次一遍0~maxn扫一下就好了

有几个坑点:

1.当k==0的时候,这个时候自己跟自己还可以算。

所以先是求不包含自己的情况,cnt[i]*(cnt[i]-1),然后一定要/2,因为多算了两遍,再加上自己跟自己的。

不是0的话就是直接cnt[i]*cnt[i^k]/2就好了。

2.因为是从点开始的,所以在根节点时,异或值为0,cnt[0]++;

3.LL

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000+100;
typedef long long LL;
int cnt;
int lala[maxn],head[maxn];
LL num[maxn];
struct node{
    int to,next,val;
}G[maxn<<1];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
    memset(lala,0,sizeof(lala));
    memset(num,0,sizeof(num));
}
void add(int u,int v,int val){
    G[++cnt].to=v;
    G[cnt].next=head[u];
    G[cnt].val=val;
    head[u]=cnt;
}
void dfs(int u,int pre,int sum){
   /// cout<<"***"<<endl;
    for(int i=head[u];i!=-1;i=G[i].next){
        int v=G[i].to;
        if(v==pre)
            continue;
        lala[v]=sum^G[i].val;
      ///  cout<<"lala[v]:"<<lala[v]<<endl;
        num[lala[v]]++;
        dfs(v,u,lala[v]);
    }
}
int main()
{
    int t,n,a,b,c,m,k;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);add(b,a,c);
        }
        dfs(1,-1,0);
        scanf("%d",&m);
        LL ans=0;
        num[0]++;

        while(m--){
            ans=0;
            scanf("%d",&k);
            for(int j=0;j<maxn;j++){
                if(k==0)
                    ans+=(num[j]*(num[j]-1));
                else
                    ans+=(num[j]*num[k^j]);
            }
            ans/=2;
            if(k==0)
                ans+=n;
            printf("%I64d\n",ans);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/xianpingping/article/details/81773360
crb