hdu5416 树形dp 树上路径异或和

D - CRB and Tree
Time Limit:4000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit  Status  Practice  HDU 5416
Appoint description:  System Crawler  (Aug 31, 2016 7:27:46 PM)

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  ≤  10^{5}  
1 ≤  Q  ≤ 10 
1 ≤  a b  ≤  N  
0 ≤  c s  ≤  10^{5}  
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.

题意: 有一个树形图,每条边有一个边权,问路径上权值异或结果为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 
#include 
#include 
#include 
#include 
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;
    queueque;
    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



你可能感兴趣的:(------树形dp)