早就听过用字典树求异或最大值,然而没做过。发现一碰到异或的题就GG,而且因为以前做过的一道类似的题(事实上并不类似)限制了思路,蠢啊= =。

题意:一棵带权的树,求任意两点间路径异或的最大值。

题解:设xor(a,b)是求a,b间路径的异或值,那么xor(a,b)=xor(root,a)^xor(root,b)。因为如果LCA(a,b)==root时结论显然成立,不然的话就会有重复走过的部分,但是异或有性质x^x=0,所以LCA(a,b)!=root结论依然成立。

这样题目就很简单了。对每一个xor(root,i)(0<i<n)建立trie,因为每个数转成二进制都是一个01组成的字符串,用来建立trie。然后对每一个xor(root,i)在trie查询最大值就好了。

  1. #include <vector>
  2. #include <list>
  3. #include <map>
  4. #include <set>
  5. #include <queue>
  6. #include <stack>
  7. #include <bitset>
  8. #include <algorithm>
  9. #include <numeric>
  10. #include <utility>
  11. #include <sstream>
  12. #include <iostream>
  13. #include <iomanip>
  14. #include <cstdio>
  15. #include <cmath>
  16. #include <cstdlib>
  17. #include <cstring>
  18. #define pk printf("lalala");
  19. #define ppp(x) printf("%d\n", x)
  20. using namespace std;
  21. #define PI acos(-1.0)
  22. #define EXP exp(1.0)
  23. #define EPS 1E-6
  24. #define clr(x,c) memset(x,c,sizeof(x))
  25.  
  26. const int KIND = ;
  27. const int MAXN = ;
  28. const int N = ;
  29. int cnt_node;
  30.  
  31. struct node{
  32. node* nt[KIND];
  33. void init(){
  34. memset(nt, , sizeof(nt));
  35. }
  36. } Heap[MAXN];
  37. node *root;
  38. int Xor[N];
  39.  
  40. inline node* new_node()
  41. {
  42. Heap[cnt_node].init();
  43. return &Heap[cnt_node++];
  44. }
  45.  
  46. void insert(node* root, int *str)
  47. {
  48. for(int i = ; i <= ; ++i){
  49. int ch = str[i];
  50. if(root->nt[ch] == NULL)
  51. root->nt[ch] = new_node();
  52. root = root->nt[ch];
  53. }
  54. }
  55.  
  56. int count(node* root, int *str)
  57. {
  58. int ans = ;
  59. for(int i = ; i <= ; ++i){
  60. int ch = str[i];
  61. int need = (ch ^ );
  62. if(root->nt[need] == NULL) {
  63. root = root->nt[ch];
  64. } else {
  65. root = root->nt[need];
  66. ans += ( << ( - i));
  67. }
  68. }
  69. return ans;
  70. }
  71.  
  72. struct Edge {
  73. int to;
  74. int w;
  75. int next;
  76. } edge[N * ];
  77.  
  78. int cnt_edge;
  79. int head[N];
  80.  
  81. void add_edge(int u, int v, int w)
  82. {
  83. edge[cnt_edge].to = v;
  84. edge[cnt_edge].w = w;
  85. edge[cnt_edge].next = head[u];
  86. head[u] = cnt_edge++;
  87. }
  88.  
  89. void dfs(int u, int fa, int val)
  90. {
  91. Xor[u] = val;
  92. for (int i = head[u]; i != -; i = edge[i].next) {
  93. int v = edge[i].to;
  94. int w = edge[i].w;
  95. if (v == fa) continue;
  96. dfs(v, u, val^w);
  97. }
  98. }
  99.  
  100. int str[N][];
  101.  
  102. int main()
  103. {
  104. int n;
  105. while (~scanf("%d",&n)) {
  106. clr(head, -);
  107. cnt_edge = ;
  108. cnt_node = ;
  109. root = new_node();
  110. int u, v, w;
  111. for (int i = ; i < n; ++i) {
  112. scanf("%d%d%d",&u, &v, &w);
  113. add_edge(u, v, w);
  114. add_edge(v, u, w);
  115. }
  116. dfs(, -, );
  117. //for (int i = 0; i < n; ++i) printf("%d ", Xor[i]); printf("\n");
  118. int ans = ;
  119. for (int i = ; i < n; ++i) {
  120. int idx = ;
  121. for (int b = ; b >= ; --b) {
  122. str[i][idx++] = Xor[i] & ( << b) ? : ;
  123. }
  124. //for (int j = 0; j < idx; ++j) printf("%d ", str[i][j]); printf("\n");
  125. insert(root, str[i]);
  126. }
  127. for (int i = ; i < n; ++i) {
  128. ans = max(ans, count(root, str[i]));
  129. }
  130. printf("%d\n", ans);
  131. }
  132. return ;
  133. }

POJ 3764 (异或+字典树)的更多相关文章

  1. POJ 2001 Shortest Prefixes(字典树)

    题目地址:POJ 2001 考察的字典树,利用的是建树时将每个点仅仅要走过就累加.最后从根节点開始遍历,当遍历到仅仅有1次走过的时候,就说明这个地方是最短的独立前缀.然后记录下长度,输出就可以. 代码 ...

  2. poj 1204 Word Puzzles(字典树)

    题目链接:http://poj.org/problem?id=1204 思路分析:由于题目数据较弱,使用暴力搜索:对于所有查找的单词建立一棵字典树,在图中的每个坐标,往8个方向搜索查找即可: 需要注意 ...

  3. poj 1056 IMMEDIATE DECODABILITY 字典树

    题目链接:http://poj.org/problem?id=1056 思路: 字典树的简单应用,就是判断当前所有的单词中有木有一个是另一个的前缀,直接套用模板再在Tire定义中加一个bool类型的变 ...

  4. POJ 2408 - Anagram Groups - [字典树]

    题目链接:http://poj.org/problem?id=2408 World-renowned Prof. A. N. Agram's current research deals with l ...

  5. POJ 1816 - Wild Words - [字典树+DFS]

    题目链接: http://poj.org/problem?id=1816 http://bailian.openjudge.cn/practice/1816?lang=en_US Time Limit ...

  6. nyoj 163 Phone List(动态字典树<trie>) poj Phone List (静态字典树<trie>)

    Phone List 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 Given a list of phone numbers, determine if it i ...

  7. poj 2503:Babelfish(字典树,经典题,字典翻译)

    Babelfish Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 30816   Accepted: 13283 Descr ...

  8. poj 2513 连接火柴 字典树+欧拉通路 好题

    Colored Sticks Time Limit: 5000MS   Memory Limit: 128000K Total Submissions: 27134   Accepted: 7186 ...

  9. POJ 1002 487-3279(字典树/map映射)

    487-3279 Time Limit: 2000MS        Memory Limit: 65536K Total Submissions: 309257        Accepted: 5 ...

随机推荐

  1. python url编码

    1.quote:使用适合URL内容的转义序列替换String中的特殊字符. 2.quote_plus:调用quote并使用“+”替换所有空格 3.unquote:使用转义字符的单字符对应物替换'%xx ...

  2. Nagios监控部署(转)

    转自 http://kyhack.blog.51cto.com/490370/213355 ky.blog 一.nagios简介        nagios是一款用于系统和网络监控的应用程序,它可以在 ...

  3. ABC: Always Be Coding——程序员面试必

    本文作者@guitardave24 ">David Byttow 是一名程序员,曾在 Google 和 Square 等公司工作过. 在正文之前,先让我们回答几个简单的问题:第一,你面 ...

  4. 封装SqlHelper

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.C ...

  5. C++中的指针与const

    刚开始接触C++时,指针和const之间的关系有点混乱,现在总结如下: 一.指向const变量的指针 #include<iostream.h> void main() { const in ...

  6. SDUT2157——Greatest Number(STL二分查找)

    Greatest Number 题目描述Saya likes math, because she think math can make her cleverer.One day, Kudo invi ...

  7. linux系统的crond服务

    linux系统中有一个服务,用来做周期性运行的例行任务,这个服务就是crond服务.执行这项服务的命令 就是crontab命令了.而linux下的任务调度又分为系统任务调度和用户任务调度两个大类. 系 ...

  8. Android开发之一个未解决的bug

    使用Activity之间传递数据的时候,出现了一个bug,但是没有找到哪里出错了. 把代码和log都记录下来,以后研究 代码: MainActivity.class package com.examp ...

  9. sencha项目升级

    对于已经开发好的sencha项目进行升级,要做的有以下几步(以sencha2.2.0升级到sencha2.3.1为例): 1,下载Sencha-2.3.1sdk,下载地址:http://cdn.sen ...

  10. A*算法完全理解

    注:原文出自Patrick Lester,一稿翻译为Panic.很久以前的老文章了,但我觉得真的非常的经典,想把它完善一下让以后的人能够更好的体会原作者和原翻译的精髓吧.我在此基础上修改了部分译文,更 ...