hdu5416 树形dp 树上路径异或和

来源:互联网 发布:美柚智能卫生巾 知乎 编辑:程序博客网 时间:2024/05/15 08:04
D - CRB and Tree
Time Limit:4000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit Status Practice HDU 5416
Appoint description: 

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 ≤ 10^{5} 
1 ≤ Q ≤ 10 
1 ≤ ab ≤ N 
0 ≤ cs ≤ 10^{5} 
It is guaranteed that given edges form a tree. 

Output

For each query, output one line containing the answer.

Sample Input

131 2 12 3 23234

Sample Output

110          

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.

题意: 有一个树形图,每条边有一个边权,问路径上权值异或结果为s 的路有多少个

思路;我们把每个点到树根的异或值求出来, xor{1, u}^xor{1,v} = xor{u,v}

为啥呢,因为1-u 和 1-v 重合的部分路径异或了两次,这部分异或值为0,如果没有重合部分,那么两条路径直接异或就是总路径的异或值了,那么每次询问, xor [u]^xor[v]=s,那么xor[u]^s=xor[v] ,求xor[v]的个数就好了,用数组保存

每个节点到树根异或值的个数,然后直接加上个数就好了,最后除以2,因为每一对路径算了两次,u-v v-u 都算了一次,当s=0时,每个点到本身也异或得0,加上n,再除以2,因为s=0,自身到自身的点只算了一次,而两个不同点

的路径都算了两次,所以要加一个n再除以二,这样刚好是 全部的路径个数

看代码:

#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#include <queue>using namespace std;const int maxn=1e6+10;int xorr[maxn],num[maxn];typedef long long LL;struct Edge{    int v,next,cap;} edge[maxn*2];int tot ,head[maxn];void init(){    tot=0;    memset(head,-1,sizeof(head));}void add_edge(int u,int v,int cap){    edge[tot].cap=cap;    edge[tot].v=v;    edge[tot].next=head[u];    head[u]=tot++;}int vis[maxn];int in[maxn],out[maxn];void bfs(int root){    memset(vis,0,sizeof(vis));    vis[root]=0;    queue<int>que;    que.push(root);    while(!que.empty())    {        int u=que.front();        que.pop();        for(int i=head[u]; i!=-1; i=edge[i].next)        {            int v=edge[i].v;            int cap=edge[i].cap;            if(!vis[v])            {                que.push(v);                xorr[v]=xorr[u]^cap;                vis[v]=1;            }        }    }}int main(){    int t,n,u,v,cap;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        init();        memset(in,0,sizeof(in));        for(int i=1; i<n; i++)        {            scanf("%d%d%d",&u,&v,&cap);            add_edge(u,v,cap);            add_edge(v,u,cap);        }        memset(xorr,0,sizeof(xorr));                bfs(1);                memset(num,0,sizeof(num));        long long ans;        for(int i=1; i<=n; i++)        {            num[xorr[i]]++;        }        int q,s,k;        scanf("%d",&q);        for(int i=0; i<q; i++)        {            scanf("%d",&s);            ans=0;            for(int i=1; i<=n; i++)            {                k=xorr[i]^s;                ans+=num[k];            }            if(s==0)                ans+=n;            ans/=2;            printf("%lld\n",ans);        }    }    return 0;}



0 0
原创粉丝点击