题目描述

给定一棵\(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的更多相关文章

  1. 洛谷 P4551 最长异或路径

    题目描述 给定一棵 nn 个点的带权树,结点下标从 11 开始到 NN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有节点权值的异或. 输入输出格式 输入格式: ...

  2. 洛谷P4551 最长异或路径

    传送门:https://www.luogu.org/problem/show?pid=4551 在看这道题之前,我们应懂这道题怎么做:给定n个数和一个数m,求m和哪一个数的异或值最大. 一种很不错的做 ...

  3. 2018.10.26 洛谷P4551 最长异或路径(01trie)

    传送门 直接把每个点到根节点的异或距离插入01trie. 然后枚举每个点在01trie上匹配来更新答案就行了. 代码: #include<iostream> #include<cst ...

  4. [luogu] P4551 最长异或路径(贪心)

    P4551 最长异或路径 题目描述 给定一棵\(n\)个点的带权树,结点下标从\(1\)开始到\(N\).寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或 ...

  5. P4551 最长异或路径

    题目描述 给定一棵 nnn 个点的带权树,结点下标从 111 开始到 NNN .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式 ...

  6. P4551 最长异或路径 (01字典树,异或前缀和)

    题目描述 给定一棵 n 个点的带权树,结点下标从 1 开始到 N .寻找树中找两个结点,求最长的异或路径. 异或路径指的是指两个结点之间唯一路径上的所有边权的异或. 输入输出格式 输入格式: 第一行一 ...

  7. Luogu P4551 最长异或路径

    题目链接 \(Click\) \(Here\) \(01Trie\)好题裸题. 取节点\(1\)为根节点,向下扫每一个点从根节点到它路径上的异或和,我们可以得到一个\(sumx[u]\). 现在路径异 ...

  8. Luogu P4551 最长异或路径 01trie

    做一个树上前缀异或和,然后把前缀和插到$01trie$里,然后再对每一个前缀异或和整个查一遍,在树上从高位向低位贪心,按位优先选择不同的,就能贪出最大的答案. #include<cstdio&g ...

  9. luoguP4551最长异或路径

    P4551最长异或路径 链接 luogu 思路 从\(1\)开始\(dfs\)求出\(xor\)路径.然后根据性质\(x\)到\(y\)的\(xor\)路径就是\(xo[x]^xo[y]\) 代码 # ...

  10. 【ybt高效进阶2-4-3】【luogu P4551】最长异或路径

    最长异或路径 题目链接:ybt高效进阶2-4-3 / luogu P4551 题目大意 给定一棵 n 个点的带权树,结点下标从 1 开始到 N.寻找树中找两个结点,求最长的异或路径. 异或路径指的是指 ...

随机推荐

  1. Chrome 134 版本新特性

    Chrome 134 版本新特性 一.Chrome 134 版本浏览器更新 1. 在桌面和 iOS 设备上使用 Google Lens 进行屏幕搜索 Chrome 版本 适用平台 发布进度 Chrom ...

  2. ohpm : 无法将“ohpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。

    ohpm : 无法将"ohpm"项识别为 cmdlet.函数.脚本文件或可运行程序的名称. 造成该问题有两个: 没有配置好 ohpm 的环境变量. 没有配置好 PowerShell ...

  3. Containerd 配置使用 Nvidia container runtime

    前言 Kubernetes 集群中 Docker 如何使用 GPU,请看这一篇 docker配置Nvidia环境,使用GPU 本文着重讲 Containerd 如何作为容器运行时来使用 GPU CRI ...

  4. golang中容易遇到的错误

    前言 在循环中,有几种情况可能会导致混乱,需要弄清楚. 循环迭代器变量中使用引用 出于效率考虑,我们经常使用单个变量来循环迭代器.但在循环中,每次循环迭代中都会有不同的值,有时候会导致未知的行为. i ...

  5. (踩坑)windows本地部署Dify ,玩转智能体、知识库

      windows 安装docker windows 本地部署deepseek windows 通过docker本地部署dify     一:安装Docker 前提: 开启Hyper-V 打开 控制面 ...

  6. 前端打包发布以及小程序发布(IIS下部署前端站点)

    作为后端程序员 一直没有摸索过前端项目的打包发布,因为项目需要 这次经历一个 前端项目以及小程序的打包发布,记录一下.   一.前端部署   部署过程种一直出现node-sass 问题 https:/ ...

  7. Docker Swarm Mode 的容器资源回收问题

    问题描述 Docker Swarm Mode 中 service 的update/scale等操作都会形成残留的容器和镜像,会造成一定程度的磁盘空间占用及缓存占用等问题... 解析 存在即合理,残留的 ...

  8. nrm

    nrm npm install -g nrm nrm ls nrm use taobao Tips:不要使用cnpm,会有些奇怪的问题,导致npm install失败. 参考

  9. C#之json字符串转xml字符串

    留爪参考 using System.Xml; // using System.Text; // using System.Runtime.Serialization.Json; //JsonReade ...

  10. leetcode每日一题:酿造药水需要的最少总时间

    引言 ​ 今天的每日一题原题是2255. 统计是给定字符串前缀的字符串数目,直接模拟,逐个匹配words中的字符串是否是s的前缀即可.更换成前几天遇到的更有意思的一题来写这个每日一题. 题目 给你两个 ...