传送门: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. SpringMVC入门学习(二)

    SpringMVC入门学习(二) ssm框架 springMVC  在上一篇博客中,我简单介绍了一下SpringMVC的环境配置,和简单的使用,今天我们将进一步的学习下Springmvc的操作. mo ...

  2. Jmeter JDBC Request 查询语句中有汉字查询结果为空的解决方法

    搜索接口我会校验返回值,查询JDBC Request 查询语句有中文字的时候查询会有问题. 解决方法很简单,在JDBC Connection Configuration的Database URL里加一 ...

  3. SpringBoot之使用Scheduled做定时任务

    定时任务有好多开源框架比如Quartz,@Scheduled是Spring的一个定时任务注解,通过注解配置就能够轻量级的定时任务,简单方便. 一.@Scheduled注解介绍 这里先贴上@Schedu ...

  4. C#winform窗体用户控件自定义事件

    C#许多事情都和事件有关系,大部分的事情我们可以通过C#自己的事件来完成,但如果我们自己新建了一个自定义控件,我们该如何定义自己想要的事件呢?下面我就来为大家粗略的讲解一番. 假设我们自定义了一个控件 ...

  5. Java基础——Ajax(二)

    一.jQuery 实现 ajax $(function(){ $("#userName").blur(function(){ // 发ajax请求 用的函数原型: $.get(ur ...

  6. 【github&&git】5、使用Git拉取GitLab上的项目

    一.安装Git(windows版.其他平台参阅) 去Git的官网,下载安装包,安装时,一路默认 二.配置Git 2.1 在任意地方,创建一个文件夹,保证该文件夹的目录全部是英文 2.2 打开新建的文件 ...

  7. Git实战手册(三): stash解惑与妙用

    0. 介绍 教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步原文地址 有空就来看看个人技术小站, 我一直都在 在实际项目开发中,总会遇到代码写到一半(没法去打commit),去开启新 ...

  8. 递归函数获得n个不重复的随机数

    // 递归函数获取不重复的随机数 var arr_end; // 用于保存最后得到的数组 function suiji(n) { var arr = [] // 产生n个随机数加入数组 for(var ...

  9. 洛谷P3899 [湖南集训]谈笑风生(线段树合并)

    题意 题目链接 Sol 线段树合并板子题,目前我看到两种写法,分别是这样的. 前一种每次需要新建一个节点,空间是\(O(4nlogn)\) 后者不需要新建,空间是\(O(nlogn)\)(面向数据算空 ...

  10. 【代码笔记】Web-手机端的meta

    一,天猫 <title>天猫触屏版</title> <meta content="text/html; charset=utf-8" http-equ ...