[NOIP模拟](codevs 1187) Xor
题目背景
OURCE:NOIP2015-SHY-7
CODEVS 1187 : 这里是链接
题目描述
求一棵带边权的树的一条最大 Xor 路径的值。这里的“路径”不一定从根到叶子结点,中间一段路径只要满足条件也可以。
输入格式
第一行,一个整数 N ,表示一颗树有 N 个节点,接下来 N - 1 行,每行三个整数 a, b, c 表示节点 a 和节点 b 之间有条权值为 c 的边。
输出格式
输出仅一行,即所求的最大值。
样例数据
Input
4
1 2 3
1 3 4
1 4 7
Output
7
备注
【数据范围】
对 40% 的输入数据 :数据退化为一条链;
另对 10% 的输入数据 : N≤1000 ;
对 100% 的输入数据 : 1≤N≤100000 , c≤231−1 。
题解 & 想法
这道题居然是个套路题,唉, 都怪自己做题太少了,而且直接输出最大值可以得 45 分, 早知道自己就骗分了。
正题 :
这道题很明显适合二进制有关(废话), 我们考虑如何表示一条路径, 我们令 dis[x] 表示从根节点到 x 节点的路径异或值, 那么从 x 到 y 的路径我们可以表示成 : dis[x] ^ dis[y], 因为从根节点到这两个节点的共同路径异或起来都为 0, 所以这个式子显然成立。
然后我们考虑对于一个 x 如何去找与之异或起来异或最大的 y, 这时候我们就可以建一颗 trie 树, insert 时从最高位跑到最低位, 寻找答案时,直接寻找与当前二进制位异或起来为 1 的点, 是一个贪心的思想, 毕竟当前为 1 一定比后面为 1 大。如果没有只有走异或为零的点。
下面贴出代码 :
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
using namespace std;
inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1; ch = getchar();
}
while(ch >= '0' && ch <= '9') {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
const int MAXN = 1e5 + 5;
int first[MAXN], to[MAXN * 2], nxt[MAXN * 2], len[MAXN * 2];
int tot, dis[MAXN], maxx, cnt, vis[MAXN];
struct point {
int son[2];
};
point tr[MAXN * 31];
inline void addedge(int x, int y, int z) {
nxt[++tot] = first[x]; first[x] = tot; to[tot] = y; len[tot] = z;
nxt[++tot] = first[y]; first[y] = tot; to[tot] = x; len[tot] = z;
}
inline void dfs(int x) {
vis[x] = 1;
for(int i = first[x]; i; i = nxt[i]) {
int y = to[i];
dis[y] = dis[x] ^ len[i];
if(!vis[y]) dfs(y);
}
}
inline void insert(int x) {
int u = 0;
for(int i = maxx; i >= 0; --i) {
int t = (x >> i) & 1;
if(!tr[u].son[t]) tr[u].son[t] = ++cnt;
u = tr[u].son[t];
}
}
inline int solve(int x) {
int u = 0, ans = 0;
for(int i = maxx; i >= 0; --i) {
int t = (x >> i) & 1;
if(!tr[u].son[t ^ 1]) ans += (t & 1) << i, u = tr[u].son[t & 1];
else ans += (t ^ 1) << i, u = tr[u].son[t ^ 1];
}
return ans ^ x;
}
int main() {
int n = read();
for(int i = 1; i <= n - 1; ++i) {
int x = read(), y = read(), z = read();
addedge(x, y, z); maxx = max(maxx, z);
}
int k = 0; while(maxx) { maxx >>= 1, ++k; } maxx = k;
dfs(1);
for(int i = 2; i <= n; ++i) insert(dis[i]);
int ans = 0;
for(int i = 2; i <= n; ++i) {
int now = solve(dis[i]);
ans = max(ans, now);
}
cout<<ans;
}
本题结束 :
感谢阅读本篇文章,喜欢的话,点个赞吧,你的鼓励就是我最大的动力
有什么意见,尽情发表吧。

本文介绍了一道NOIP模拟赛中的Xor路径问题,通过构建Trie树实现路径最大Xor值的查找,并提供了完整的解题思路及代码实现。
302

被折叠的 条评论
为什么被折叠?



