最长异或路径(01trie+最大异或对)
最长异或路径
板子题,但是如果把边权改成了点权的话好像就不好做了,暂时还没想好
题意:给定一棵带边权的树,求最大的异或路径。
思路:
- 令每个节点的权值为从根到当前节点的路径上边权异或值,则此问题就被转化为普通的最大异或对了
- 最大异或对就没啥说的了,按顺序(随便什么顺序)把每个点加入 01trie中,然后在每加入一个点前先判定当前点能与 01trie中异或的最大值(贪心得搞一下就行了),把所有求出的最大值再取一个最大值就是答案了
题面描述
#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}
const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-7;
int N;
int head[maxn], nxt[maxn*2], to[maxn*2], w[maxn*2], tot;
int a[maxn];
int node[maxn<<5][2], cnt;
inline void add_edge(int u, int v, int w) {
++tot, to[tot]=v, nxt[tot]=head[u], ::w[tot]=w, head[u]=tot;
++tot, to[tot]=u, nxt[tot]=head[v], ::w[tot]=w, head[v]=tot;
}
inline void max(int &a, int b) { if(a<b) a=b; }
void dfs(int u, int fa) {
for(int i=head[u]; i; i=nxt[i]) {
int v=to[i];
if(v!=fa) {
a[v]=a[u]^w[i];
dfs(v,u);
}
}
}
inline void insert(int p) {
int now=0;
for(int i=30; i>=0; --i) {
int s=p>>i&1;
if(!node[now][s]) node[now][s]=++cnt;
now=node[now][s];
}
}
inline int match(int p) {
int now=0, ans=0;
for(int i=30; i>=0; --i) {
int s=p>>i&1;
if(node[now][!s]) ans|=1<<i, now=node[now][!s];
else now=node[now][s];
}
return ans;
}
int main() {
//ios::sync_with_stdio(false); cin.tie(0);
N=read();
for(int i=1; i<N; ++i) {
int u=read(), v=read(), w=read();
add_edge(u,v,w);
}
dfs(1,0);
insert(a[1]); int ans=0;
for(int i=2; i<=N; ++i) max(ans,match(a[i])), insert(a[i]);
cout<<ans<<endl;
}