Description

给定 \(n\) 个点的带边权树,求一条异或和最大的简单路径

Input

第一行是点数 \(n\)

下面 \(n - 1\) 行每行三个整数描述这棵树

Output

输出一个数代表答案

Hint

\(1~\leq~n~\leq~10^5~,~1~\leq~w~<~2^{31}\),其中 \(w\) 是最大边权

Solution

考虑由于自身异或自身对答案无贡献,对于两个点 \(u,v\),他们简单路径上的异或和即为他们分别向根节点求异或和的两个值的疑惑值。

然后考虑枚举每个点,设它向根求异或和的值为 \(c\),寻找另一个能够最大化异或值的点。显然要从高到低考虑。高位不够优秀的可以直接扔掉,我们考虑到底 \(i\) 位时,所有没有被扔掉的点中,如果 \(c\) 的第 \(i\) 位为 \(1\),则为了让答案更大,我们尽可能的选择第 \(i\) 位为 \(0\) 的点,反过来同理。

于是问题变成了动态判断是否存在符合要求的异或和。我们建立一棵 \(01\) trie来维护所有的异或和,然后在树上反着走即可。

时空复杂度 \(O(n~\log w)\)。不过略微有点小卡空间

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
int top=0;
do {OPT::buf[++top] = char(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 100010;
const int maxm = 200010;
const int maxt = 6200010; struct Edge {
Edge *nxt;
int to, v;
};
Edge eg[maxm], *hd[maxn]; int ecnt;
inline void cont(ci from, ci to, ci v) {
Edge &e = eg[++ecnt];
e.to = to; e.nxt = hd[from]; e.v = v; hd[from] = &e;
} struct Tree {
Tree *son[2];
};
Tree qwq[maxt], *rot;
int top; int n, ans;
int dist[maxn]; void reading();
void dfs(ci, ci);
void buildroot();
void build(Tree*, ci, ci);
int check(Tree*, ci, ci); int main() {
freopen("1.in", "r", stdin);
qr(n);
reading();
dfs(1, 0);
buildroot();
for (int i = 1; i <= n; ++i) build(rot, dist[i], 31);
for (int i = 1; i <= n; ++i) ans = std::max(ans, check(rot, dist[i], 31) ^ dist[i]);
qw(ans, '\n', true);
return 0;
} void reading() {
int a, b, c;
for (int i = 1; i < n; ++i) {
a = b = c = 0; qr(a); qr(b); qr(c);
cont(a, b, c); cont(b, a, c);
}
} void dfs(ci u, ci fa) {
for (Edge *e = hd[u]; e; e = e->nxt) {
int &to = e->to;
if (to == fa) continue;
dist[to] = dist[u] ^ e->v; dfs(to, u);
}
} void buildroot() {
rot = qwq; top = 1;
} void build(Tree *u, ci v, ci cur) {
if (cur < 0) return;
int k = static_cast<bool>((1 << cur) & v);
build(u->son[k] ? u->son[k] : u->son[k] = qwq + (top++), v, cur - 1);
} int check(Tree *u, ci v, ci cur) {
if (cur < 0) return 0;
int k = (static_cast<bool>((1 << cur) & v)) ^ 1;
return u->son[k] ? (check(u->son[k], v, cur - 1) | (k << cur)) : check(u->son[k ^ 1], v, cur - 1) | ((k ^ 1) << cur);
}

Summary

对于异或和一类的题目,考虑自身异或两遍对答案无贡献的情况。

动态判断一个串是否存在可以使用踹树来维护。

【trie树】【P4551】 最长异或路径的更多相关文章

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

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

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

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

  3. P4551 最长异或路径

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

  4. 洛谷 P4551 最长异或路径

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

  5. 洛谷P4551 最长异或路径

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

  6. Luogu P4551 最长异或路径

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

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

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

  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. shutil模块详解

    python常用模块目录 注意:shutil经常遇到路径需要转义一下才能执行,在字符串前面加 r转义  r" " 1.shutil常用方法 import shutil# 删除目录 ...

  2. 马赛克是否无法逆转?Python简单消除,看片无忧!

    图片水印,轻松去除 前段时间玩过了全民K歌,不知道大家是否玩过,还是做得挺好的,就我这嗓子都能唱出张学友的味道,其中更是有消除噪声的功能,就是朋友们都在吃鸡大叫,我在旁边唱歌依然不受影响. 既然声音可 ...

  3. 允许使用root远程ssh登录(Ubuntu 16.04)

    今天装了ubuntu16和17,发现还是ubuntu16看着顺眼,所以以后决定用ubuntu16, 然后想换语言发现更新失败,所以想换成中国的源,但是vm里面复制粘贴不了,所以想用secureCRT连 ...

  4. Beta发布--PSP DAILY软件功能说明书2.0

    一.开发背景 你在完成了一周的软件工程作业后,需要提交一个PSP图表,里面有4项,如下所示: 1.本周PSP表格,包含每项任务的开始.中断.结束.最终时间,格式如下: 2.本周进度条,包含从开始到现在 ...

  5. 设计与实现分离——面向接口编程(OO博客第三弹)

    如果说继承是面向对象程序设计中承前启后的特质,那么接口就是海纳百川的体现了.它们都是对数据和行为的抽象,都是对性质和关系的概括.只不过前者是纵向角度,而后者是横向角度罢了.今天呢,我想从设计+语法角度 ...

  6. 20135234mqy 实验四

    北京电子科技学院(BESTI) 实     验    报     告 课程:java程序设计 班级:1352  姓名:mqy  学号:20135234 成绩:            指导教师:娄嘉鹏  ...

  7. 20145214《网络对抗》MAL_后门原理与实践

    20145214<网络对抗>MAL_后门原理与实践 基础问题回答 (1)例举你能想到的一个后门进入到你系统中的可能方式? 网页上查找资料时有时会不小心点到弹出来的广告,如果这个广告是个钓鱼 ...

  8. 20162314 《Program Design & Data Structures》Learning Summary Of The First Week

    20162314 2017-2018-1 <Program Design & Data Structures>Learning Summary Of The First Week ...

  9. linux 常用命令-ps命令

    ps(process status):进程状态相关命令 1.

  10. Oracle安装后出现的问题

    安装oracle没有勾选"安装模板数据库",可以通过执行以下命令进行修改: cd $ORACLE_HOME/rdbms/admin 到这个目录下sqlplus /as sysdba ...