hdu 5416 树上的异或(思路题)

题意:给定一棵树,树上任意两点的距离为其路径上的边权的异或值,求距离等于某个值的点的对数。

思路:这道题关键是要利用异或的性质。异或最基本的一个性质是和同一个数异或两次不发生改变。而对于这道题来说求出任意两点间的距离是不现实的,但是利用异或的性质,如果我们有了每个点到根的距离,就能间接得到任意两点间的距离,对于任意两点u和v,他们之间的距离就是他们到根的距离异或起来。因为不在u到v路径上的那些边权(即lca(u,v)到根的路径上的边)被异或了两次等于没算,想到这一点就好做了,我们只要借助hash来统计答案即可,注意为查询为0的情况。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N = 200001;
 9 int mp[N];
10 int head[N];
11 int n, e;
12 
13 void init()
14 {
15     e = 0;
16     memset( head, -1, sizeof(head) );
17     memset( mp, 0, sizeof(mp) );
18 }
19 
20 struct Edge 
21 {
22     int v, next, w;
23 } edge[N];
24 
25 void addEdge( int u, int v, int w )
26 {
27     edge[e].v = v;
28     edge[e].w = w;
29     edge[e].next = head[u];
30     head[u] = e++;
31 }
32 
33 void dfs( int u, int fa, int val )
34 {
35     mp[val]++;
36     for ( int i = head[u]; i != -1; i = edge[i].next )
37     {
38         int v = edge[i].v, w = edge[i].w;
39         if ( v == fa ) continue;
40         dfs( v, u, val ^ w );
41     }
42 }
43 
44 int main ()
45 {
46     int t;
47     scanf("%d", &t);
48     while ( t-- )
49     {
50         scanf("%d", &n);
51         init();
52         for ( int i = 1; i < n; i++ )
53         {
54             int u, v, w;
55             scanf("%d%d%d", &u, &v, &w);
56             addEdge( u, v, w );
57             addEdge( v, u, w );
58         }
59         dfs( 1, -1, 0 );
60         int q;
61         scanf("%d", &q);
62         while ( q-- )
63         {
64             int tt;
65             scanf("%d", &tt);
66             ll ans = 0;
67             if ( tt == 0 )
68             {
69                 for ( int i = 0; i < N; i++ )
70                 {
71                     ans += ( ll ) mp[i] * ( mp[i] + 1 ) / 2;
72                 }
73             }
74             else
75             {
76                 for ( int i = 0; i < N; i++ )
77                 {
78                     int tmp = tt ^ i;
79                     if ( tmp >= N ) continue;
80                     ans += ( ll ) mp[i] * mp[tmp];
81                 }
82                 ans = ans >> 1;
83             }
84             printf("%I64d\n", ans);
85         }
86     }
87     return 0;
88 }

 

posted @ 2015-08-20 18:40  hxy_has_been_used  阅读(883)  评论(0编辑  收藏  举报