• 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
    ", ans);
    85         }
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    SpringBoot详解(二)——
    SpringBoot详解(一)——
    数据库三大范式
    Mysql备份
    mysql索引
    mysql事务
    几种数据库查找的案例
    点击加载更多
    layer、弹出框
    验证码倒计时
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4746041.html
Copyright © 2020-2023  润新知