【ybt高效进阶2-4-3】【luogu P4551】最长异或路径
最长异或路径
题目链接:ybt高效进阶2-4-3 / luogu P4551
题目大意
给定一棵 n 个点的带权树,结点下标从 1 开始到 N。寻找树中找两个结点,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或。
思路
首先看到要异或的值最大,我们要想到可以用 Trie 树来贪心弄。
但是它好像不知道怎么弄,那我们先不管它。
那我们看到是一棵树,那我们可以试着统计 \(i\) 到根节点(我这里设是 \(1\))的异或路径的长度是多少。
那我们考虑能不能用这个表示出任意两个点之间的异或路径。
这里先给出结论,其实就是两个点到根节点的异或路径异或起来得出的值。
我们来证明:
分两种情况,分别是一个点在另一个点到根节点的路径上,要么就是两条路径是分开的,不会相交。
- 第一种,那我们可以知道一个点,就是一个值异或它自己就是 \(0\),就会消掉。那你想想,第一种情况时这个图:
那 \(1\) 号点到根节点的异或路径就是 \(a\),\(2\) 号点到根节点的异或路径是 \(a\oplus b\),我们要的是 \(b\)。
那你发现,把它们异或起来,就是 \(a\oplus a\oplus b=b\)。(两个 \(a\) 异或起来抵消掉了) - 第二种,那我们可以画图。
那 \(1\) 号点到根节点的异或路径就是 \(a\),\(2\) 号点到根节点的异或路径是 \(b\),我们要的是 \(a\oplus b\)。
那你发现,把它们异或起来,就是 \(a\oplus b\)。
那你就可以一开始预处理出到根节点的异或路径,然后枚举两个点,然后算这两个点的异或路径,然后取最大值。
但是很明显这样是 \(O(n^2)\) 的,它会超时。
那我们就想一想有什么方法可以快速求最大值的。
想想我们之前一开始想用什么方法?
没错,就是 Trie 树。
我们可以把每个点到根节点的异或路径都放进 Trie 树里面构造。
然后每次枚举你要的异或路径的另一个点,然后跟 Trie 树里面的路径匹配找到最大值。
前面做过一题就是求这个最大值的,主要的就是用了贪心的思想。
从高位向低位枚举,然后如果有跟你这一位不同的就优先选,同时统计这一位异或之后是 \(1\) 对数的贡献。然后如果没有不同的,就看有没有相同的。
(因为毕竟你可以这一位相同,然后尽可能让后面更高的位不同,这样的贡献就更大)
那如果想相同不相同都没有,那就只能以当前的贡献退出了。
(如果想看之前的那一题可以点我查看,不过我只写在了 csdn,博客园里没有,因为比较简单)
然后对这些最大值选一个最大的,就是答案了。
代码
#include<cstdio>
#include<iostream>
using namespace std;
struct node {
int x, to, nxt;
}e[200001];
struct Tree {
int son[2];
}trie[1000001];
int n, x, y, z, le[100001], KK, go, KKK, ans;
void add(int x, int y, int z) {//邻接表
e[++KK] = {z, y, le[x]}; le[x] = KK;
e[++KK] = {z, x, le[y]}; le[y] = KK;
}
void build(int num) {//Trie树建树
int now = 0;
for (int i = 31; i >= 0; i--) {
go = num >> i & 1;
if (!trie[now].son[go]) trie[now].son[go] = ++KKK;
now = trie[now].son[go];
}
}
int find(int num) {
int now = 0, re = 0;
for (int i = 31; i >= 0; i--) {//从高位到低位贪心看
go = num >> i & 1;
if (trie[now].son[go ^ 1]) {//先看能不能有这一位不同
now = trie[now].son[go ^ 1];
re |= 1 << i;
}
else if (trie[now].son[go]) now = trie[now].son[go];//只能相同
else return re;//都没有,就只能退出了
}
return re;
}
void dfs1(int now, int father, int num) {//建出从根节点到 i 点的异或路径构成的 Trie 数
build(num);
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father)
dfs1(e[i].to, now, num ^ e[i].x);
}
void dfs2(int now, int father, int num) {//得出与现在的路径异或能得到的最大值
ans = max(ans, find(num));
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father)
dfs2(e[i].to, now, num ^ e[i].x);
}
int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
scanf("%d %d %d", &x, &y, &z);
add(x, y, z);
}
dfs1(1, 0, 0);
dfs2(1, 0, 0);
printf("%d", ans);
return 0;
}
【ybt高效进阶2-4-3】【luogu P4551】最长异或路径的更多相关文章
- [luogu] P4551 最长异或路径(贪心)
P4551 最长异或路径 题目描述 给定一棵\(n\)个点的带权树,结点下标从\(1\)开始到\(N\).寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或 ...
- Luogu P4551 最长异或路径
题目链接 \(Click\) \(Here\) \(01Trie\)好题裸题. 取节点\(1\)为根节点,向下扫每一个点从根节点到它路径上的异或和,我们可以得到一个\(sumx[u]\). 现在路径异 ...
- Luogu P4551 最长异或路径 01trie
做一个树上前缀异或和,然后把前缀和插到$01trie$里,然后再对每一个前缀异或和整个查一遍,在树上从高位向低位贪心,按位优先选择不同的,就能贪出最大的答案. #include<cstdio&g ...
- 洛谷P4551 最长异或路径
传送门:https://www.luogu.org/problem/show?pid=4551 在看这道题之前,我们应懂这道题怎么做:给定n个数和一个数m,求m和哪一个数的异或值最大. 一种很不错的做 ...
- 2018.10.26 洛谷P4551 最长异或路径(01trie)
传送门 直接把每个点到根节点的异或距离插入01trie. 然后枚举每个点在01trie上匹配来更新答案就行了. 代码: #include<iostream> #include<cst ...
- P4551 最长异或路径
题目描述 给定一棵 nnn 个点的带权树,结点下标从 111 开始到 NNN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式 ...
- 洛谷 P4551 最长异或路径
题目描述 给定一棵 nn 个点的带权树,结点下标从 11 开始到 NN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有节点权值的异或. 输入输出格式 输入格式: ...
- P4551 最长异或路径 (01字典树,异或前缀和)
题目描述 给定一棵 n 个点的带权树,结点下标从 1 开始到 N .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式: 第一行一 ...
- 洛谷【P4551】最长异或路径
浅谈\(Trie\):https://www.cnblogs.com/AKMer/p/10444829.html 题目传送门:https://www.luogu.org/problemnew/show ...
随机推荐
- 【Linux】用yum来下载rpm,而不安装
方法一:yum yum命令本身就可以用来下载一个RPM包,标准的yum命令提供了--downloadonly(只下载)的选项来达到这个目的. $ sudo yum install --download ...
- [oracle] exp-00091
产生原因: 在数据库的服务器端和客户端字符集不同的情况下,导出(dump)数据库表时,会产生这个错误.虽然产生这个错误,但好像对导入没有影响. 解决办法: 查看服务器端字符集: 打开SQLPLUS,执 ...
- Linux服务器上迁移项目路径,修改nginx配置,迁移及备份MongoDB数据库流程 (超详细)!!!
缘由:客户服务器项目路径不是很合理,导致Jenkins自动部署时还需要添加路径后再更新部署,所以需要把项目路径统一和规范化. 迁移项目路径,保证路径合规,同时做好备份和迁移.迁移后先安装好依赖. 项目 ...
- +load和+initialize方法调用时机
一.+load方法什么时候调用 +load方法会在runtime加载类.分类时调用(程序运行起来会先去加载调用+load 跟你引用没有引用其头文件没有关系).每个类.分类的+load,在程序运行过程中 ...
- MySQL数据库基础知识及优化
MySQL数据库基础知识及优化必会的知识点,你掌握了多少? 推荐阅读: 这些必会的计算机网络知识点你都掌握了吗 关于数据库事务和锁的必会知识点,你掌握了多少? 关于数据库索引,必须掌握的知识点 目录 ...
- java 记录数据持续变化时间
1.需求:获取count为null和不为null的持续变化 [{count=0, time=0}, {count=10, time=1000}, {count=20, time=2000}, {cou ...
- pytest fixtures装饰器的使用
一.pytest中可以使用@pytest.fixture 装饰器来装饰一个方法,被装饰方法的方法名可以作为一个参数传入到测试方法中.可以使用这种方式来完成测试之前的初始化,也可以返回数据给测试函数. ...
- Mybatis plus 报错Invalid bound statement (not found) 终极解决办法
我产生的错误原因是写的mapper继承BaseMapper没有添加泛型: 点进去: 为了解决这个bug,网上很多人也提出了解决办法:1.检查xml文件的namespace是否正确 2.Mapper.j ...
- 奇艺iOS移动端网络优化实践 | 请求成功率优化篇 原创 Charles 爱奇艺技术
奇艺iOS移动端网络优化实践 | 请求成功率优化篇 原创 Charles 爱奇艺技术
- mysqldump 内存消耗
MySQL :: MySQL 8.0 Reference Manual :: 4.5.4 mysqldump - A Database Backup Program https://dev.mysql ...