题型:数据结构
题意:
树有n个结点,每条边上有一个权值。
u到v的路径值,为从u到v的路径上所有边的权值的异或值。
求所有路径中的最大值。
分析:
对于许多个异或值里取最值的处理,字典树一直都是个好方法。
根据异或的一个性质,a⊕b = (a⊕c)⊕(c⊕b)
我们可以预处理出每一个节点到根节点的路径值,这个用dfs解决。
这样我们可以求出任意两个点的路径值。
但是有n个值,暴力求最值,O(n^2)复杂度过高。
采用字典树处理。
将这n个值转换为32位二进制串插入01字典树。
然后遍历n个数,查找每个数在字典树中能够异或出的最大值。
处理方法为,从高位开始,每次都尽量查找相反的值,是0就查1,是1就查0,查不到的话就查原值。因为高位是尽可能为1,所以就能保证查找出来的异或值最大。
最后选一个最大值为答案。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M = 32*100000+10;
int n;
struct G {
struct E {
int u,v,w,next;
} e[M];
int le,head[M];
void init() {
le = 0;
mt(head,-1);
}
void add(int u,int v,int w) {
e[le].u = u;
e[le].v = v;
e[le].w = w;
e[le].next = head[u];
head[u] = le++;
}
} g;
int val[100010];
int fa[100010];
void dfs(int u) {
for(int i=g.head[u]; ~i; i=g.e[i].next) {
int v = g.e[i].v;
if(v != fa[u]) {
fa[v] = u;
val[v] = val[u] ^ g.e[i].w;
dfs(v);
}
}
}
class Trie_tree { //字典树 前缀树
struct node {
int next[2],ptr,num;// ptr在字典中的位置,num此结点出现几次,
void init() {
ptr=-1;
num=0;
mt(next,0);
}
} s[M];
int ls,p;
public:
int ch[33];
int tmp[33];
void init() {
s[1].init();
p=0;
ls=2;
}
void toer(int x) {
mt(ch,0);
int pre = 0;
while(x) {
ch[pre] = x%2;
pre++;
x /= 2;
}
for(int i=pre; i<32; i++) {
ch[i] = 0;
}
for(int i=0,j=31; i<j; i++,j--) {
ch[i] ^= ch[j];
ch[j] ^= ch[i];
ch[i] ^= ch[j];
}
}
void INSERT(int x) {
toer(x);
int head = 1;
for(int k=0; k<32; k++) {
int id = ch[k];
if(!s[head].next[id]) {
s[head].next[id] = ls;
s[ls++].init();
}
head = s[head].next[id];
s[head].num ++;
}
s[head].ptr=p++;
}
int QUERY(int x) {
toer(x);
for(int i=0; i<32; i++) {
if(ch[i]) ch[i] = 0;
else ch[i] = 1;
}
mt(tmp,0);
int head = 1;
for(int k=0; k<32; k++) {
if(s[head].next[ch[k]]) {
tmp[k] = 1;
head = s[head].next[ch[k]];
} else {
tmp[k] = 0;
head = s[head].next[(ch[k]+1)%2];
}
}
// for(int i=0;i<32;i++){
// printf("%d ",tmp[i]);
// }
// puts("");
int sum = 0;
int mul = 1;
for(int i=31; i>=0; i--) {
if(tmp[i]) {
sum += mul;
}
mul<<=1;
}
// printf("%d\n",sum);
return sum;
}
} ts;
int main() {
while(~scanf("%d",&n)) {
int u,v,w;
g.init();
for(int i=0; i<n-1; i++) {
scanf("%d%d%d",&u,&v,&w);
g.add(u,v,w);
g.add(v,u,w);
}
mt(val,0);
mt(fa,-1);
dfs(0);
// for(int i=0;i<n;i++){
// printf("%d\n",val[i]);
// }
ts.init();
for(int i=0; i<n; i++) {
ts.INSERT(val[i]);
}
int maxn = -1;
for(int i=0; i<n; i++) {
maxn = max(maxn,ts.QUERY(val[i]));
}
printf("%d\n",maxn);
}
return 0;
}