传送门:https://www.luogu.org/problem/show?pid=4551

在看这道题之前,我们应懂这道题怎么做:给定n个数和一个数m,求m和哪一个数的异或值最大。

一种很不错的做法是将n个数按二进制从最高位到低位建立一个trie树,然后把m放在trie树上跑一遍。

因为是从高位到低位存的,所以对于每一位,我们只要贪心让这一位的异或值得1。即如果m得当前位是1,就在trie树上找0;否则就找1.若能找到,ans的这一位就是1,否则是0.

如果上述这道水题会了的话,这道题就不难想了。

首先预处理每一个点到根节点的异或距离,为什么这么做呢,看下图

比如点7到根节点的距离dis[7] = f ^ b ^ a,点6到根节点的距离dis[6] = c ^ a,则dis[7] ^ dis[6] = f ^ b ^ c ^ a ^ a = f ^ b ^ c,恰好为6到7的距离。

因此我们就可以像上面这道题一样,将所有dis放到trie树里面,然后再让每一个dis[i]跑一遍trie树,最后结果取max即可。

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<vector>
#include<cctype> //isdigit
using namespace std;
typedef long long ll;
#define enter printf("\n")
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
inline ll read() {
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {
last = ch;
ch = getchar();
}
while(isdigit(ch)) {
ans = ans * + ch - '';
ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x) {
if(x < ) {
putchar('-');
x = -x;
}
if(x == ) {
putchar('');
return;
}
int q[], N = ;
q[] = ;
while(x) {
q[++N] = x % ;
x /= ;
}
while(N) {
putchar('' + q[N]);
--N;
}
} int n;
vector<int> v[maxn], c[maxn];
int cost[maxn];
bool vis[maxn];
void bfs(int s) { //bfs预处理每一个点到根节点的距离
queue<int> q;
q.push(s);
vis[s] = ;
cost[s] = ;
while(!q.empty()) {
int now = q.front();
q.pop();
for(int i = ; i < (int)v[now].size(); ++i) {
if(!vis[v[now][i]]) {
vis[v[now][i]] = ;
cost[v[now][i]] = cost[now] ^ c[now][i];
q.push(v[now][i]);
}
}
}
}
struct Trie {
int ch[maxn * ][], tot;
Trie() {
memset(ch, , sizeof(ch));
tot = ;
}
void Insert(int x) { //建树
int now = ;
for(int i = ; i >= ; --i) {
int w = (x >> i) & ;
if(!ch[now][w]) ch[now][w] = ++tot;
now = ch[now][w];
}
}
int query(int x) {
int now = , ret = ;
for(int i = ; i >= ; --i) {
int w = (x >> i) & ;
if(!ch[now][!w]) now = ch[now][w];
else {
now = ch[now][!w]; //若和x这一位不同的边存在,就走这条边,同时ret的这一位标记成1
ret += ( << i);
}
}
return ret;
}
} trie; int ans = ; int main() {
n = read();
for(int i = ; i < n; ++i) {
int a = read(), b = read(), cost = read();
v[a].push_back(b);
c[a].push_back(cost);
v[b].push_back(a);
c[b].push_back(cost);
}
bfs();
for(int i = ; i <= n; ++i)
trie.Insert(cost[i]);
for(int i = ; i <= n; ++i)
ans = max(ans, trie.query(cost[i]));
write(ans);
enter;
return ;
}

洛谷P4551 最长异或路径的更多相关文章

  1. 洛谷 P4551 最长异或路径

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

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

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

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

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

  4. P4551 最长异或路径

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

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

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

  6. Luogu P4551 最长异或路径

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

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

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

  8. luoguP4551最长异或路径

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

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

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

随机推荐

  1. Maven教程3(依赖管理)

    Maven教程2(Eclipse配置及maven项目) Maven项目,依赖,构建配置,以及构件:所有这些都是要建模和表述的对象.这些对 象通过一个名为项目对象模型(Project Object Mo ...

  2. netty源码解解析(4.0)-13 Channel NIO实现: 关闭和清理

    Channel提供了3个方法用来实现关闭清理功能:disconnect,close,deregister.本章重点分析这个3个方法的功能的NIO实现. disconnect实现: 断开连接 disco ...

  3. 一个小时学会PHP

    一.PHP概要 PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广 ...

  4. JS通过百度地图API获取当前定位信息

    $(function(){ var latlon=null; //ajax获取用户所在经纬度 $.ajax({ url:"http://api.map.baidu.com/location/ ...

  5. 总结:JDK1.5-JDK1.8各个新特性

    JDK1.5-JDK1.8各个新特性 JDK各个版本的新特性 要了解一门语言,最好的方式就是要能从基础的版本进行了解,升级的过程,以及升级的新特性,这样才能循序渐进的学好一门语言.以下介绍一下JDK1 ...

  6. 深入理解JVM——对象

    对象的创建 虚拟机遇到一条new指令时,首先检查指令的参数能否在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载.解析和初始化过.如果没有,必须先执行相应的类加载过程. 接下 ...

  7. Linux环境变量详解与应用

    在bash shell中,环境变量分为: >全局变量 >局部变量 全局变量,不仅对shell可见,对其子进程也可见 查看预设的全局环境变量: ghostwu@dev:~$ printenv ...

  8. 微信服务号获取openid方法

    public function tetst(){ if(!isset($_GET['code'])){ $APPID = $this->app_id; $ran = rand(1,100); / ...

  9. 【读书笔记】iOS-iCloud介绍

    iCloud是一种面向消费者市场的云存储服务,苹果公司已经做了大量的工作让用户能够平滑过渡到iCloud,不过对开发者而言这意味着新的负担. 怎样使用iCloud? 你可以使用2种方式在你的应用中使用 ...

  10. CoreCRM 开发实录 —— 基于 AntDesign 的新 UI

    上一篇说到,因为有新朋友加入,对前端开发有了新的要求.原来基于 Bootstrap 的 UI 就不要了.在网上(其实是 GitHub 上)逛了几圈,最后使用了 antd-admin 这个框架做为基础模 ...