HDU 5416 CRB and Tree(前缀思想+DFS)

CRB and Tree

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

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 ab 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 ≤ ab ≤ N
0 ≤ cs ≤ 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
3
2
3
4
 

 

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.

 

 

题目链接:HDU 5416

和NBUT上一道题很像,只是前者是统计路径异或和为0的个数,这个就稍微复杂一点,统计异或和为s的个数,显然异或和不管是线性的还是树形的都是符合异或性质的

即prefix_{R}^prefix_{L-1}=prefix_{L~R},由于给的是边权而不是点权,就不用处理LCA这个点的问题了,设s=i^j,则j=s^i,DFS一遍得到储存前缀异或和xorsum个数的cnt[]数组,然后分类讨论一下,若i==j由于u可以等于v,显然组合可能数为cnt[i]*(cnt[i]+1)/2(由于int的取整问题把除以二放到最后),否则显然是cnt[i]*cnt[j],最后由于你遍历的时候除了遍历到0其他情况会重复计算,比如s=1时,遍历到2会组合到3,遍历到3又组合到2,因此若s不为0的话则答案要除以2。

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=1e5+7;
const int R=1<<17;
struct edge
{
    int to,nxt,w;
};
edge E[N<<1];
int head[N],tot;
LL cnt[R];

void init()
{
    CLR(head,-1);
    tot=0;
    CLR(cnt,0);
}
inline void add(int s,int t,int w)
{
    E[tot].to=t;
    E[tot].w=w;
    E[tot].nxt=head[s];
    head[s]=tot++;
}
void dfs(int u,int sum,int pre)
{
    ++cnt[sum];
    for (int i=head[u]; ~i; i=E[i].nxt)
    {
        int v=E[i].to;
        if(v!=pre)
            dfs(v,sum^E[i].w,u);
    }
}
int main(void)
{
    int tcase,n,m,a,b,s,c,i;
    scanf("%d",&tcase);
    while (tcase--)
    {
        init();
        scanf("%d",&n);
        for (i=0; i<n-1; ++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        dfs(1,0,-1);
        scanf("%d",&m);
        while (m--)
        {
            LL ans=0;
            scanf("%d",&s);
            for (i=0; i<R; ++i)
            {
                if(i==(s^i))
                    ans+=(cnt[i]*(cnt[i]+1))>>1;
                else
                    ans+=(cnt[i]*cnt[s^i]);
            }
            if(s)
                ans>>=1;
            printf("%I64d\n",ans);
        }
    }
    return 0;
}
posted @ 2016-11-28 21:28  Blackops  阅读(203)  评论(0编辑  收藏  举报