最长异或路径

时间限制: 2000MS2000MS2000MS 空间限制: 64MB64MB64MB

题目描述

在一棵有边权的树上,一条路径ppp的异或长度定义为ppp上所有边权的异或和
xorlength(p)=⊕e∈pw(e)_{xor}length(p)=\oplus_{e \in p}^w(e)xor​length(p)=⊕e∈pw​(e)
⊕⊕⊕是异或符号。
我们认为一条路径是最长异或路径当且经当它拥有最长的异或长度。给定一棵有边权的树,你能找出最长异或路径吗?

输入格式

输入包括若干组测试数据。每个测试点的第一行包括一个整数nnn(1≤n≤100000)(1≤n≤100000)(1≤n≤100000),接下来n−1n-1n−1行每行包括3个整数u(0≤u&lt;n),v(0≤v&lt;n),w(0≤w&lt;231)u(0 ≤ u &lt; n),v(0 ≤ v &lt; n),w(0 ≤ w &lt; 2^{31})u(0≤u<n),v(0≤v<n),w(0≤w<231)表示在节点uuu和vvv之间有一条长为www的边。

输出格式

对于每组测试数据输出最长异或路径的异或长度。
样例输入
444
000 111 333
111 222 444
111 333 666

样例输出

777

提示

最长异或路径是 0−&gt;1−&gt;20-&gt;1-&gt;20−>1−>2,长度是7(=3⊕4)7 (=3 ⊕ 4)7(=3⊕4)
以上翻译由作者原创,不喜勿喷,转载请注明出处


解析

首先对于静态的树上两点间异或路径,我们可以通过树上前缀和解决。
任取一点为根,统计出根到每个点uuu路径上的异或长度d[u]d[u]d[u]。
那么对于任意两点u,vu,vu,v之间的异或路径就=d[u]=d[u]=d[u] xorxorxor d[v]d[v]d[v] xorxorxor d[lca(u,v)]d[lca(u,v)]d[lca(u,v)] xorxorxor d[lca(u,v)]d[lca(u,v)]d[lca(u,v)] =d[u]=d[u]=d[u] xorxorxor d[v]d[v]d[v] (x(x(x xorxorxor x=0)x = 0)x=0)


于是,问题就变成了在nnn个数中取出两个数使得它们的异或值最大。
如果直接O(n2)O(n^2)O(n2)暴力枚举显然是会超时的。
我们考虑二进制下每一位对答案的影响:

  1. 如果该位可以为111,那么无论如何都比该位000最终的答案更大
  2. 当两个数在二进制下某一位不同时,异或后的答案才为111
    因此我们可以通过TrieTrieTrie树来实现这个操作。

具体实现:

  1. 对于每个d[i]d[i]d[i]将其转化成二进制数后从前往后插入TrieTrieTrie树中。
  2. 对于每个d[i]d[i]d[i]去已经生成好的TrieTrieTrie树中二分,若当前节点有与当前位不同的儿子节点,则往该儿子节点搜索,否则只能往与当前位相同的儿子节点搜索。

Tips:Tips:Tips:因为有多组数据,注意将TrieTrieTrie树手动清空。


代码

#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100005;
const int maxe = 100005;
int edgenum;
int Next[maxe << 1] , vet[maxe << 1] , val[maxe << 1] , head[maxn];
int d[maxn];
int len;
bool a[35];
int id;
int max(int x , int y){return x > y ? x : y;}
void swap(int &x , int &y){x ^= y , y ^= x , x ^= y;}
int read()
{char ch = getchar();while(ch < '0' || ch > '9') ch = getchar();int res = 0;while(ch >= '0' && ch <= '9') res = (res << 3) + (res << 1) + (ch ^ 48) , ch = getchar();return res;
}
void add_edge(int u , int v , int cost)
{edgenum++;Next[edgenum] = head[u];vet[edgenum] = v;val[edgenum] = cost;head[u] = edgenum;
}
void dfs(int u , int fa)
{for(int e = head[u];e;e = Next[e]){int v = vet[e];if(v == fa) continue;d[v] = d[u] ^ val[e];dfs(v , u);}
}
struct Trie
{private:int cnt;int ch[35 * maxn][2] , d_id[35 * maxn];public:int rt;void clear(){rt = 1 , cnt = 1;memset(ch , 0 , sizeof ch);}void insert(int &u , int loc){if(!u) u = ++cnt;if(loc > len) {d_id[u] = id; return;}insert(ch[u][a[loc]] , loc + 1);}int query(int u , int loc){if(loc > len) return d_id[u];if(ch[u][a[loc] ^ 1]) return query(ch[u][a[loc] ^ 1] , loc + 1);return query(ch[u][a[loc]] , loc + 1);}
}trie;
void change(int x)
{len = 32;for(int i = 1;i <= len;i++) a[i] = x >> len - i & 1;
}
int main()
{int n;while(scanf("%d",&n) == 1){edgenum = 0;for(int i = 1;i <= n;i++) head[i] = 0;for(int i = 1;i < n;i++){int u = read() + 1 , v = read() + 1 , cost = read();add_edge(u , v , cost);add_edge(v , u , cost);}for(int i = 1;i <= n;i++) d[i] = 0;dfs(1 , 0);trie.clear();for(int i = 1;i <= n;i++) change(d[i]) , id = i , trie.insert(trie.rt , 1);int ans = 0;for(int i = 1;i <= n;i++) change(d[i]) , ans = max(ans , d[trie.query(trie.rt , 1)] ^ d[i]);printf("%d\n",ans);}return 0;
}

POJ3764(树上前缀和+Trie树)相关推荐

  1. Trie树(字典树)详细知识点及其应用

    Trie,又经常叫前缀树,字典树等等.它有很多变种,如后缀树,Radix Tree/Trie,PATRICIA tree,以及bitwise版本的crit-bit tree.当然很多名字的意义其实有交 ...

  2. 分门别类刷leetcode——高级数据结构(字典树,前缀树,trie树,并查集,线段树)

    目录 Trie树(字典树.前缀树)的基础知识 字典树的节点表示 字典树构造的例子 字典树的前序遍历 获取字典树中全部单词 字典树的整体功能 字典树的插入操作 字典树的搜索操作 字典树的前缀查询 字典树 ...

  3. 实现字典树(前缀树、Trie树)并详解其应用

    今天看到一个比较好的数据结构,字典树,做一下记录,以供自己后期复习和读者朋友的参考. 1.定义 字典树又称单词查找树.前缀树.Trie树等,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序 ...

  4. Trie树实现前缀自动补全 + AC自动机实现敏感词过滤

    文章目录 背景 扩展 AC自动机 背景 最近参与了某业务系统的开发, 需要根据城市的名字简称,找到其官方的完整名称.比如云南的大理,其实其完整的名称是大理白族自治州.可以参考官方的行政区划,点这里. ...

  5. Trie树合并 + SG函数 ---- BZOJ4730. Alice和Bob又在玩游戏(动态开点Trie 树上全局异或标记 + 合并 + 博弈论)

    题目大题 题目大意: 解题思路: 首先我们对于子树u的SG函数为SG函数为SG函数为 ⨁是异或和\bigoplus是异或和⨁是异或和 SG[u]=mex{⨁w∈(w的父亲在u到v的路径上)SG[w]∣ ...

  6. YBTOJ:前缀询问(trie树)

    文章目录 题目描述 解析 代码 题目描述 解析 (没有做出来,这个ans的处理方式其实也不难想-qwq) 考虑把T都作为模板串加入trie树 加入每个模板串自然就是按照i顺序的 所以我们在插入t的时候 ...

  7. trie树查找前缀串_Trie数据结构(前缀树)

    trie树查找前缀串 by Julia Geist Julia·盖斯特(Julia Geist) A Trie, (also known as a prefix tree) is a special ...

  8. 前缀树(字典树,单词查找树,Trie树)

    参考网址:https://blog.csdn.net/u013949069/article/details/78056102?utm_source=copy 概述 前缀树又名字典树,单词查找树,Tri ...

  9. java单词匹配算法_前端学数据结构与算法(八): 单词前缀匹配神器-Trie树的实现及其应用...

    前言 继二叉树.堆之后,接下来介绍另外一种树型的数据结构-Trie树,也可以叫它前缀树.字典树.例如我们再搜索引擎里输入几个关键字之后,后续的内容会自动续上.此时我们输入的关键词也就是前缀,而后面的就 ...

  10. python Trie树和双数组TRIE树的实现. 拥有3个功能:插入,删除,给前缀智能找到所有能匹配的单词...

    #coding=utf-8 #字典嵌套牛逼,别人写的,这样每一层非常多的东西,搜索就快了,树高26.所以整体搜索一个不关多大的单词表 #还是O(1). ''' Python 字典 setdefault ...

最新文章

  1. tcp和udp多线程的epoll服务器+客户端源代码 - brucema的个人空间 - 开源中国社区
  2. spark standalone zookeeper HA部署方式
  3. Caffe上用SSD训练和测试自己的数据
  4. 你不知道的javascript事件
  5. 一些学Web前端最常见的错误分享
  6. 剑指offer之树的子结构
  7. JArchitect v4.0发布
  8. 计算机操作员实操高级试题,计算机操作员高级实操(以往考过,可做平时练习素材)答题.doc...
  9. webpack入门+react环境配置 1
  10. 项目管理需要使用到的图表
  11. mysql 超时连接错误码_mysql链接超时错误
  12. 字符串的数组形式与指针形式
  13. vue3监听网页窗口关闭
  14. PhotoShop基础
  15. shp数据中文乱码的一种恢复方法
  16. java祖玛_Canvas小练习_祖玛游戏01
  17. java服务端限流框架,美团大众点评服务框架Pigeon
  18. Jmeter使用BeanShell取样器调用Python脚本
  19. python缺点特性_day1---python的基础特性
  20. 区块链安全初探(二):区块链的层次

热门文章

  1. 华硕笔记本bios设置u盘启动
  2. 黑马程序员--黑马程序员的入学流程真的“很黑”
  3. word里双横线怎么打_Word中下划线怎么打出来
  4. 六种用JavaScript检测出当前浏览器是否是无头浏览器( selenium headless browser)
  5. MD5,SHA1,SHA256,NTLM,LM等Hash在线破解网站收集
  6. 原 《老路用得上的商学课》86-90学习笔记
  7. php怎么画五星红旗,php基于GD库画五星红旗的方法_php技巧
  8. 对PHP中GD库的一些画图函数、及函数参数的学习总结(一)
  9. 使用mqtt.fx连接腾讯云IoT Cloud——超详细
  10. 【Git】Git国内官网下载地址、淘宝镜像下载地址以及卸载安装