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. JavaWeb-Servlet-Tomcat

    Servlet就是运行在服务器上的Java类.Servlet容器为javaweb应用提供运行时环境,负责管理Servlet和JSP的生命周期,以及管理它们的共享数据. Servlet容器软件——Tom ...

  2. django_models后台管理myarya

    arya重点代码 # urls.py from django.urls import path,re_path,include from arya.service import v1 urlpatte ...

  3. Vue 入门之概念

    Vue 简介 Vue 是一个前端的双向绑定类的框架,发音[读音 /vjuː/, 类似于 [view].新的 Vue 版本参考了 React 的部分设计,当然也有自己独特的地方,比如 Vue 的单文件组 ...

  4. 【quickhybrid】如何实现一个Hybrid框架

    章节目录 [quickhybrid]如何实现一个跨平台Hybrid框架 [quick hybrid]架构一个Hybrid框架 [quick hybrid]H5和Native交互原理 [quick hy ...

  5. 第二阶段每日站立会议Third Day

    昨天对图片显示的大小进行调整 今天对于程序中的字体显示进行细化修改,使界面更美观 遇到的问题:当图片太小时,显示一块灰色区域,不美观

  6. Task 10 统计从1到某个整数之间出现的1的次数

    任务:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数. 要求: 写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数.例如 f(12) = 5. 在3 ...

  7. 【流程图】购物车、三级菜单、sed替换

  8. B-tree&B+tree&数据库索引原理

    B-tree&B+tree:https://www.cnblogs.com/vianzhang/p/7922426.html 数据库索引原理:https://www.cnblogs.com/a ...

  9. unix网络编程——I/O多路复用之epoll

    1. 基本概念 当程序进行IO时,如果数据尚未准备好,那么IO将处于阻塞状态.当某个进程有多个打开的文件,比如socket,那么其后的所有准备好读写的文件将受到阻塞的影响而不能操作.不借助线程,单一进 ...

  10. By.cssSelector定位元素一个不足发现

     这个如果用cssSelector定位,代码如下,此时输出的数值是0 System.out.println(driver.findElements(By.cssSelector("div[c ...