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. 【Alpha】特殊情况通知

    由于我本人(SivilTaram)连续工作两周半,压力过大,今早出现心绞痛,故请求休假一天.今日不开Scrum Meeting,其余队员团队项目正常进行.

  2. hive-2.3.3安装

    1.下载hive-2.3.3 下载地址 http://archive.apache.org/dist/hive/hive-2.3.3 解压,编辑/etc/profile添加HIVE_HOME,保存文件 ...

  3. 封装,策略,Asp换脸

    封装.策略 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...

  4. srTCM和trTCM介绍

    本文是用于QoS Meter功能的算法的RFC的阅读笔记.DPDK的QoS_meter示例程序用的就是这个算法. srTCM srTCM的英文全称是Single Rate Three Color Ma ...

  5. jquery-numberformatter插件

    项目地址:https://code.google.com/p/jquery-numberformatter/ 非jquery版:https://github.com/andrewgp/jsNumber ...

  6. [建树(非二叉树)] 1106. Lowest Price in Supply Chain (25)

    1106. Lowest Price in Supply Chain (25) A supply chain is a network of retailers(零售商), distributors( ...

  7. js访问对象属性的两种方法

    var obj={name:'fuuf',age:19} 第一种,用.访问 obj.name 第二种 用[]访问 obj['name']  //此时name是字符串,要加引号 注意事项 使用第二种方法 ...

  8. beta阶段成果展示博客

    跟着我们一一点一点揭开蒙娜丽莎的微笑 - 本次beta阶段之前,我们团队,对其他组在事后诸葛亮期间对我们的评价进行深刻的审视,特别是缺点方面,开了好几次的站立会议,专门讨论beta的主要方向和任务.最 ...

  9. node入门学习(一)

    一.安装node.js 方式很多npm,git等,新手建议从官网上直接去下载node的安装包.一键安装. 二.创建一个web服务器. const http = require('http'); htt ...

  10. linux使用密文生成os账户

    1.生成账户 [hufangrui@xxx ~]$ openssl passwd -1Password: Verifying - Password: $1$szzkROBZ$GYxffRLp8K5vW ...