【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】NFS搭建及使用详解
环境:CentOS release 6.8 server 192.168.25.100 client1 192.168.25.101 client2 192.168.25.102 1.服务端操作 1 ...
- leetcode 864. 获取所有钥匙的最短路径(BFS,状态压缩)
题目链接 864. 获取所有钥匙的最短路径 题意 给定起点,要求在最短步骤内收集完所有钥匙,遇到每把锁之前只有 有对应的钥匙才能够打开 思路 BFS+状态压缩典型题目 先确定起点和总的钥匙数目,其次难 ...
- ctfshow—web—web2
打开靶机,根据提示是SQL注入 打开后看到登录窗口 方法一.手工注入 抓取数据包 开始SQL注入测试 利用万能密码,登录成功 查看回显位置 查询数据库 查询数据库内数据表 如果想整齐一点显示可以添加g ...
- 力软最新版本与.netCore版本
功能强大,直接上图: 加微信或QQ交流开发技术:25489181 netcore版本 版本优势: .NET Core是适用于 Windows.Linux 和 macOS 的免费.开源托管的计算机软件框 ...
- 在EXCEL中如何同时冻结行与列?
鼠标所在的单元格的位置 ,决定了你冻结的行和列.如: 冻结第一行与第一列, 只需要将鼠标置于单元格在第二列,第二行. 点击冻结
- Vue之事件绑定
Vue事件绑定 点击事件 @click="事件名" or v-on:click="事件名" 结构部分: <el-button type="pri ...
- ip_hash(不推荐使用) 会话粘性问题分析 Cookie 的 Session Sticky
Nignx 连接tomcat时会话粘性问题分析_changyanmanman的专栏-CSDN博客_后端tomcat导致 前端elb中断 https://blog.csdn.net/cymm_liu/a ...
- py, pyc, pyw, pyo, pyd Compiled Python File (.pyc) 和Java或.NET相比,Python的Virtual Machine距离真实机器的距离更远
https://my.oschina.net/renwofei423/blog/17404 1. PyCodeObject与Pyc文件 通常认为,Python是一种解释性的语言,但是这种说法 ...
- C++ Primer Plus读书笔记(一)开始学习C++
1.using namespace std; 注意一下命名空间的概念,不编译这句话,可能就要用 std::cout << std::endl 这种写作方式了. 这句话放在函数内部,只对该 ...
- Python 学习笔记(1)
Mac下载安装Python mac 系统自带有python .但就最新的mac系统而言,它自带的python版本为2.*版本. 虽然不影响对于老python项目的运行,但3.*版本中很多语法都发生了改 ...