卧薪尝胆,厚积薄发。
最长异或路径
Date: Sun Nov 04 16:09:41 CST 2018 In Category: NoCategory

Description:

给一棵 $n$ 个点的树,边有边权,求一条路径边权异或和最大。
$1\leqslant n\leqslant 100000$

Solution:

随便选一个点作为根,然后对于每个点求出他到根的边权异或和,那么两个点间的路径异或和就是两个端点值的异或,因为 $LCA$ 到根那部分被消掉了,所以用一个 $trie$ 查询异或最大值即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
inline int rd()
{
register int res = 0,f = 1;
register char c = getchar();
while(!isdigit(c))
{
if(c == '-')f = -1;
c = getchar();
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res * f;
}
int n;
#define MAXN 100010
struct edge
{
int to,nxt,v;
}e[MAXN << 1];
int edgenum = 0;
int lin[MAXN] = {0};
void add(int a,int b,int c)
{
e[++edgenum] = (edge){b,lin[a],c};lin[a] = edgenum;
e[++edgenum] = (edge){a,lin[b],c};lin[b] = edgenum;
return;
}
struct node
{
int tr[2];
}t[MAXN * 30];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
void insert(int x)
{
int cur = root;
for(int i = 30;i >= 0;--i)
{
int w = (x >> i) & 1;
if(t[cur].tr[w] == 0)t[cur].tr[w] = newnode();
cur = t[cur].tr[w];
}
return;
}
int calc(int x)
{
int cur = root;
int res = 0;
for(int i = 30;i >= 0;--i)
{
int w = (x >> i) & 1;
if(t[cur].tr[w ^ 1] == 0)cur = t[cur].tr[w];
else
{
cur = t[cur].tr[w ^ 1];
res ^= (1 << i);
}
}
return res;
}
bool v[MAXN];
int ans = 0;
void dfs(int k,int sum)
{
ans = max(ans,calc(sum));
insert(sum);
v[k] = true;
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(v[e[i].to])continue;
dfs(e[i].to,sum ^ e[i].v);
}
return;
}
int main()
{
scanf("%d",&n);
int a,b,c;
for(int i = 1;i < n;++i)
{
a = rd();b = rd();c = rd();
add(a,b,c);
}
dfs(1,0);
cout << ans << endl;
return 0;
}
In tag: 字符串-trie
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡