洛谷P4551 最长异或路径 trie
题目描述
给定一棵\(n\)个点的带权树,结点下标从\(1\)开始到\(N\)。寻找树中找两个结点,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或。
输入格式
第一行一个整数\(N\),表示点数。
接下来 \(n−1\) 行,给出 \(u\),\(v\),\(w\) ,分别表示树上的 \(u\) 点和 \(v\) 点有连边,边的权值是 \(w\)。
输出格式
一行,一个整数表示答案。
输入输出样例
输入 #1
4
1 2 3
2 3 4
2 4 6
输出 #1复制
7
说明/提示
最长异或序列是1-2-3,答案是 7 (=3 ⊕ 4)
数据范围
\(1\le n \le 100000;0 < u,v \le n;0 \le w < 2^{31}\)
分析
先利用xor的性质:\(x \oplus y \oplus y=x\),提示我们只需要一遍电风扇dfs计算所有点到根节点(随便用1来当根节点)的\(xor\)路径即可。那么现在就可以\(O(n^2)\)做这道题了。
当然\(O(n^2)\)过\(10^5\)是不可能的(可以一试嘿
考虑用\(trie\)进行优化。
设\(f_i\)为\(i\)号节点到根节点的\(xor\)路径,对于每一个\(f_i\)直接插入\(0/1trie\),查询时从高位到低位贪心:
- 如果当前节点存在一个与要查询的\(f_i\)的这一位相反的儿子,那么就走向这一个节点,\(xor\)值的该位赋为一。
- 反之走向另一个节点,因为这一层走的节点与\(f_i\)的这一位相同,相同的值\(xor=0\)。
那么只要从每一个点进行一遍查询,即可查询到从这个点出发能够得到的最大\(xor\)路径。
取最大值即可。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define re register
#define debug printf("Now is %d\n",__LINE__);
using namespace std;
template<class T>inline void read(T&x)
{
char ch=getchar();
while(!isdigit(ch))ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
}
inline int read()
{
int x=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
x=ch-'0';ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x;
}
int G[55];
template<class T>inline void write(T x)
{
int g=0;
if(x<0) x=-x,putchar('-');
do{G[++g]=x%10;x/=10;}while(x);
for(re int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
}
int n;
int head[200010],ver[200010],nxt[200010],w[200010];
int cnt;
void insert(int a,int b,int c)
{
nxt[++cnt]=head[a];
head[a]=cnt;
ver[cnt]=b;
w[cnt]=c;
nxt[++cnt]=head[b];
head[b]=cnt;
ver[cnt]=a;
w[cnt]=c;
}
//dfs
int f[100010];
void dfs(int x,int now,int fa)
{
f[x]=now;
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]==fa) continue;
dfs(ver[i],now^w[i],x);
}
}
//trie
int trie[5000010][2];
int trie_cnt;
void insert(int x)
{
int now=0;
for(int i=31;i>=0;i--)
{
if(!trie[now][(x>>i)&1]) trie[now][(x>>i)&1]=++trie_cnt;
now=trie[now][(x>>i)&1];
}
}
int ask(int x)
{
int now=0,res=0;
for(int i=31;i>=0;i--)
{
bool y=(x>>i)&1;
if(trie[now][!y]) now=trie[now][!y],res+=1<<i;
else now=trie[now][y];
}
return res;
}
int main()
{
n=read();
for(int i=1,a,b,c;i<n;i++)
{
a=read();
b=read();
c=read();
insert(a,b,c);
}
dfs(1,0,0);
for(int i=1;i<=n;i++) insert(f[i]);
int ans=0;
for(int i=1;i<=n;i++) ans=max(ans,ask(f[i]));
cout<<ans;
return 0;
}
小结
过了样例,但是第一遍写的时候忘记写\(ask\)中的那一个else了!导致调了半天都不知道哪里错了,叫Tringmo过来一看他就发现了。
/kk
洛谷P4551 最长异或路径 trie的更多相关文章
- 洛谷 P4551 最长异或路径
题目描述 给定一棵 nn 个点的带权树,结点下标从 11 开始到 NN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有节点权值的异或. 输入输出格式 输入格式: ...
- 洛谷P4551 最长异或路径
传送门:https://www.luogu.org/problem/show?pid=4551 在看这道题之前,我们应懂这道题怎么做:给定n个数和一个数m,求m和哪一个数的异或值最大. 一种很不错的做 ...
- 2018.10.26 洛谷P4551 最长异或路径(01trie)
传送门 直接把每个点到根节点的异或距离插入01trie. 然后枚举每个点在01trie上匹配来更新答案就行了. 代码: #include<iostream> #include<cst ...
- [luogu] P4551 最长异或路径(贪心)
P4551 最长异或路径 题目描述 给定一棵\(n\)个点的带权树,结点下标从\(1\)开始到\(N\).寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或 ...
- P4551 最长异或路径
题目描述 给定一棵 nnn 个点的带权树,结点下标从 111 开始到 NNN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式 ...
- P4551 最长异或路径 (01字典树,异或前缀和)
题目描述 给定一棵 n 个点的带权树,结点下标从 1 开始到 N .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式: 第一行一 ...
- Luogu P4551 最长异或路径
题目链接 \(Click\) \(Here\) \(01Trie\)好题裸题. 取节点\(1\)为根节点,向下扫每一个点从根节点到它路径上的异或和,我们可以得到一个\(sumx[u]\). 现在路径异 ...
- Luogu P4551 最长异或路径 01trie
做一个树上前缀异或和,然后把前缀和插到$01trie$里,然后再对每一个前缀异或和整个查一遍,在树上从高位向低位贪心,按位优先选择不同的,就能贪出最大的答案. #include<cstdio&g ...
- luoguP4551最长异或路径
P4551最长异或路径 链接 luogu 思路 从\(1\)开始\(dfs\)求出\(xor\)路径.然后根据性质\(x\)到\(y\)的\(xor\)路径就是\(xo[x]^xo[y]\) 代码 # ...
- 【ybt高效进阶2-4-3】【luogu P4551】最长异或路径
最长异或路径 题目链接:ybt高效进阶2-4-3 / luogu P4551 题目大意 给定一棵 n 个点的带权树,结点下标从 1 开始到 N.寻找树中找两个结点,求最长的异或路径. 异或路径指的是指 ...
随机推荐
- Chrome 134 版本新特性
Chrome 134 版本新特性 一.Chrome 134 版本浏览器更新 1. 在桌面和 iOS 设备上使用 Google Lens 进行屏幕搜索 Chrome 版本 适用平台 发布进度 Chrom ...
- ohpm : 无法将“ohpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
ohpm : 无法将"ohpm"项识别为 cmdlet.函数.脚本文件或可运行程序的名称. 造成该问题有两个: 没有配置好 ohpm 的环境变量. 没有配置好 PowerShell ...
- Containerd 配置使用 Nvidia container runtime
前言 Kubernetes 集群中 Docker 如何使用 GPU,请看这一篇 docker配置Nvidia环境,使用GPU 本文着重讲 Containerd 如何作为容器运行时来使用 GPU CRI ...
- golang中容易遇到的错误
前言 在循环中,有几种情况可能会导致混乱,需要弄清楚. 循环迭代器变量中使用引用 出于效率考虑,我们经常使用单个变量来循环迭代器.但在循环中,每次循环迭代中都会有不同的值,有时候会导致未知的行为. i ...
- (踩坑)windows本地部署Dify ,玩转智能体、知识库
windows 安装docker windows 本地部署deepseek windows 通过docker本地部署dify 一:安装Docker 前提: 开启Hyper-V 打开 控制面 ...
- 前端打包发布以及小程序发布(IIS下部署前端站点)
作为后端程序员 一直没有摸索过前端项目的打包发布,因为项目需要 这次经历一个 前端项目以及小程序的打包发布,记录一下. 一.前端部署 部署过程种一直出现node-sass 问题 https:/ ...
- Docker Swarm Mode 的容器资源回收问题
问题描述 Docker Swarm Mode 中 service 的update/scale等操作都会形成残留的容器和镜像,会造成一定程度的磁盘空间占用及缓存占用等问题... 解析 存在即合理,残留的 ...
- nrm
nrm npm install -g nrm nrm ls nrm use taobao Tips:不要使用cnpm,会有些奇怪的问题,导致npm install失败. 参考
- C#之json字符串转xml字符串
留爪参考 using System.Xml; // using System.Text; // using System.Runtime.Serialization.Json; //JsonReade ...
- leetcode每日一题:酿造药水需要的最少总时间
引言 今天的每日一题原题是2255. 统计是给定字符串前缀的字符串数目,直接模拟,逐个匹配words中的字符串是否是s的前缀即可.更换成前几天遇到的更有意思的一题来写这个每日一题. 题目 给你两个 ...