您的位置:首页 > 其它

[NOIP模拟]xor

2017-10-06 17:03 363 查看
题目描述

题目背景: SOURCE:NOIP2015-SHY-7

求一棵带边权的树的一条最大 Xor 路径的值。这里的“路径”不一定从根到叶子结点,中间一段路径只要满足条件也可以。

输入格式:

第一行,一个整数 N ,表示一颗树有 N 个节点,接下来 N-1 行,每行三个整数 a,b,c 表示节点 a 和节点 b 之间有条权值为 c 的边。

输出格式:

输出仅一行,即所求的最大值。

样例输入:

4

1 2 3

1 3 4

1 4 7

样例输出:

7

数据范围:

对 40% 的输入数据 :数据退化为一条链;

另对 10% 的输入数据 :N≤1000;

对 100% 的输入数据 :1≤N≤100000,c≤231−1。

题目分析

首先我们得知道异或的性质:a^b^b=a;即xor运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变。

那么我们就可以先dfs,求出从根节点到每一个子节点的路径异或值,记为yh[i]。那么yh[u]^yh[v]就是从u到v路径异或值(由上面的性质可知)。

所以我们把所有yh转成二进制数插入trie树,建好后,对于每个yh进去查询,因为异或的规则是不同为1, 相同为0,所以查询时尽量走相反的路径,这样最后求出来就会从当前点出发路径异或的最大值。最后比较一下就是ans。

附代码

#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std;

const int N=1e5+10;
int n,po,tot,nxt[N*2],first
,to[N*2],w[N*2],yh
,maxz,num;
int len,x,y,z;
bool vis
;

struct node{
int son[2];
}tr[N*32];

int readint()
{
char ch;int i=0,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') {ch=getchar();f=-1;}
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}

void create(int x,int y,int z)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
to[tot]=y;
w[tot]=z;
}

void dfs(int src,int fa)
{
for(int e=first[src];e;e=nxt[e])
if(to[e]!=fa)
{
yh[to[e]]=w[e]^yh[src];
dfs(to[e],src);
}
}

void insert(int x)//建树
{
int po=0;
for(int i=len-1;i>=0;i--)
{
int t=(x>>i)&1;//求出对应二进制数的每一位
if(tr[po].son[t]==0) tr[po].son[t]=++num;
po=tr[po].son[t];
}
}

int find(int x)
{
int po=0;
for(int i=len-1;i>=0;i--)
{
int t=(x>>i)&1;
if(tr[po].son[t^1]!=0)//存在相反的路径
{
po=tr[po].son[t^1];
x|=(1<<i);//因为相反,所以原数的那一位异或后必然为1,而或运算,|1就直接把那位修改1。
}
else//不存在相反的路径
{
po=tr[po].son[t];
x^=(t<<i);//因为相同,所以原数的那一位异或后必然为0,于是就异或它本身。
}
}
return x;
}

int main()
{
//freopen("xor.in","r",stdin);
//freopen("xor.out","w",stdout);

n=readint();
for(int i=1;i<n;i++)
{
x=readint();y=readint();z=readint();
if(z>maxz) maxz=z;
create(x,y,z);
create(y,x,z);
}
dfs(1,0);
while(maxz) {maxz>>=1;len++;}//计算最大数的二进制数的位数,因为要相同位数插入,小的前面要补0。
for(int i=1;i<=n;i++)
insert(yh[i]);
for(int i=1;i<=n;i++)
maxz=max(maxz,find(yh[i]));
printf("%d",maxz);

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