传送门: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. openssl rsautl和openssl pkeyutl(文件的非对称加密)

    openssl系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html rsautl是rsa的工具,相当于rsa.dgst的部分功能集合,可用于生成 ...

  2. C#基础 数据类型 类型转换

    本节主要讲解数据类型和各类型之间的转换,两点都是重点,难点在于各种转换的活学活用. 一   数据类型 (一)基本数据类型 1  值类型 (1)整形         int                ...

  3. ASP.NET Web API 启用跨域访问

    自定义特性 要在WebApi中实现JSONP,一种方式是实现自定义特性  http://stackoverflow.com/questions/9421312/jsonp-with-asp-net-w ...

  4. webpack4 系列教程: 前言

    1. 什么是webpack? 前端目前最主流的javascript打包工具,在它的帮助下,开发者可以轻松地实现加密代码.多平台兼容.而最重要的是,它为前端工程化提供了最好支持.vue.react等大型 ...

  5. 设计模式之观察者模式(Observer)

    观察者模式通常的叫法叫做订阅-发布模式,类似于报刊杂志的订阅,观察者和被观察者就是读者和邮局的关系,读者先要在邮局订阅想要的报刊,当报刊发行时,邮局会将报刊邮寄到读者家里.观察者(Observer)和 ...

  6. java反射与动态代理的理解

    一.什么是反射机制? 反射的官方定义是这样的:在运行状态中,对于任意的一个类,都能够知道这个类的所有属性和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息及动态调用类对象 ...

  7. Nginx + 阿里云SSL + tomcat 实现https访问代理

    第一步:阿里云申请云盾证书服务 第二步:下载证书 第三步:修改Nginx配置 1. 证书文件214033834890360.pem,包含两段内容,请不要删除任何一段内容. 2. 如果是证书系统创建的C ...

  8. KVM虚拟化研究-1

    使用qemu-img创建镜像 例子: [root@HOST31 rybtest]# qemu-img create -f raw /rybtest/test1.raw 1G 使用qemu-img查看镜 ...

  9. Android事件总线(四)源码解析otto

    前言 上一篇文章中讲到了otto的用法,这一篇我们来讲一下otto的源码.可能有人觉得otto过时了,但是通过源码我们学习的是高手设计otto时的设计理念,这种设计理念是不过时的. otto各个类的作 ...

  10. Expo大作战(三十九)--expo sdk api之 DocumentPicker,Contacts(获取手机联系人信息),Branch

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...