您的位置:首页 > 其它

[POJ 3764] The xor-longest Path

2018-03-13 19:32 471 查看

Description

多组数据

给你一颗树,

然后求一条最长异或路径,

异或路径长度定义为两点间简单路径上所有边权的异或和。

Solution

首先 dfs 一遍,求出所有的点到根节点(随便选一个)的边权的异或和,用 D 数组来存下。

不难发现,树上 x 到 y 的路径上所有边权的 xor 结果就等于 D[x] xor D[y]。这是因为根据 xor 的性质 (a xor a = 0),“ x 到根 ” 和 “ y 到根 ”这两条路径重叠的部分恰好抵消掉。

所以,问题就变成了从 D[1]~D
这 N 个数中选出两个,xor 的结果最大。

可以用 Trie 树来快速求解。

upd:wa了不下十次数组开大点就能A..  Trie的空间是玄学=.=

Code

 

#include<cstdio>
#include<cstring>
#include<iostream>
#define N 200015
#define int long long
using namespace std;

bool vis[N<<1];
int head[N<<1],d[N<<1];
int n,cnt,tot,maxn;

struct Edge{
int to,nxt,dis;
}edge[N<<2];

struct Trie{
int zero,one;
}trie[N<<3];

void add(int x,int y,int z){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
edge[cnt].dis=z;
head[x]=cnt;
}

void clear(){
tot=maxn=0;
memset(d,0,sizeof d);
memset(vis,0,sizeof vis);
memset(head,0,sizeof head);
memset(edge,0,sizeof edge);
memset(trie,0,sizeof trie);
}

void dfs(int now){
vis[now]=1;
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(vis[to]) continue;
d[to]=d[now]^edge[i].dis;
dfs(to);
}
}

void insert(int x){
int now=0;
for(int i=30;~i;i--){
if(x&(1<<i)){
if(!trie[now].one) trie[now].one=++tot;
now=trie[now].one;
}
else{
if(!trie[now].zero) trie[now].zero=++tot;
now=trie[now].zero;
}
}
}

int query(int x){
int now=0,sum=0;
for(int i=30;~i;i--){
int k=!(x&(1<<i));
if(k){
if(trie[now].one) sum|=1<<i,now=trie[now].one;
else now=trie[now].zero;
}
else{
if(trie[now].zero) sum|=1<<i,now=trie[now].zero;
else now=trie[now].one;
}
}
return sum;
}

signed main(){
while((scanf("%lld",&n))!=EOF){
clear();
for(int x,y,z,i=1;i<n;i++){
scanf("%lld%lld%lld",&x,&y,&z);
add(x+1,y+1,z);add(y+1,x+1,z);
}
dfs(1);
for(int i=1;i<=n;i++)
maxn=max(maxn,query(d[i])),insert(d[i]);
printf("%lld\n",maxn);
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: