P4551 最长异或路径 The XOR-longest Path 题解
The XOR-longest Path
Description
原题来自:POJ 3764
给定一棵 n 个点的带权树,求树上最长的异或和路径。
Input Format
第一行一个整数 n,接下来 n−1 行每行三个整数 u,v,w,表示 u,v 之间有一条长度为 w 的边。
Output Format
输出一行一个整数,表示答案。
Sample
样例输入
4
1 2 3
2 3 4
2 4 6
样例输出
7
样例解释
最长的异或和路径是 1→2→3
它的长度是
3⨁4=7。
注意:结点下标从 1 开始到 N。
注:x⨁y 表示 x 与 y 按位异或。
Hint
对于 100% 的数据,1 ≤ n ≤ 10^5 , 1 ≤ u,v ≤ n , 0 ≤ w ≤ 2^31;
---------------------------优雅的分界线----------------------------
正片开始
首先首当其冲先想到的是暴力,即两遍dfs跑图,第一遍预处理,第二遍求根到深度最大的叶子节点所有边的异或,求出答案
然而当我们把暴力代码交上去的时候,迎接我们的不是T,而是WA......
为什么会WA呢?
我们再仔细地读一遍题—————— 树上最长的异或和路径
哎呀!
不是从根到叶子节点的最长路,而是最长的异或和路径;
最近犯唐诗真是越来越严重了呀
所以我们考虑 dijk Tire树。
仔细一想,这不就是0-1 Tire树嘛
只要将每个点到根的异或距离预处理一下,然后都存到0-1树里,就跟 P10471 最大异或对 The XOR Largest Pair (0-1树的板子题)一样了啊
然后只要求其中的最大值就行了
最后,代码附上,完结撒花
#include<bits/stdc++.h>
#define int long long
#define Blue_Archive return 0
#define rint register int
using namespace std;
const int N = 5000010;
const int p = 1313131;
const int mod = 1e9 + 7;
int n;
int ans;
int val[N];
int cnt;
int son[N][2];//0-1 trie树
int to[N];//前向星
int nxt[N];//前向星
int h[N];//前向星
int w[N];//前向星
int tot = -1;//前向星
inline int max(int x,int y)
{
return x > y ? x : y;
}
inline int min(int x,int y)
{
return x < y ? x : y;
}
inline void add(int u,int v,int ww)
{
nxt[++ tot] = h[u];
to[tot] = v;
w[tot] = ww;
h[u] = tot;
}
inline void update(int val,int x)
{
for(int i = (1 << 30);i;i >>= 1)
{
bool t = i & val;
if(!son[x][t]) son[x][t] = ++ cnt;
x = son[x][t];
}
}
inline int Shiroko(int val,int x)
{
int ans = 0;
for(int i = (1 << 30);i;i >>= 1)
{
bool t = i & val;
if(!son[x][!t])
{
x = son[x][t];
}
else
{
x = son[x][!t];
ans += i;
}
}
return ans;
}
inline void Hoshino(int x,int f)
{
for(int i = h[x];~i;i = nxt[i])
{
int v = to[i];
if(v == f) continue;
val[v] = val[x] ^ w[i];
Hoshino(v,x);
}
}
// inline void hifumi(int x,int dp)
// {
// if(dp > 1) ans ^= val[x];
// else ans = val[x];
// if(fa[x]) hifumi(fa[x],dp + 1);
// else return;
// }
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
memset(h,-1,sizeof(h));
cin >> n;
// cnt = 1;
for(int i = 1,u,v,ww;i < n;i ++)
{
cin >> u >> v >> ww;
add(u,v,ww);
add(v,u,ww);
}
Hoshino(1,-1);
for(int i = 1;i <= n;i ++)
{
update(val[i],0);
}
ans = 0;
for(int i = 1;i <= n;i ++)
{
ans = max(ans,Shiroko(val[i],0));
}
cout << ans << "\n";
Blue_Archive;
}
/////////////////////////////
// Shiroko //
/////////////////////////////
与你的日常,便是奇迹

浙公网安备 33010602011771号