[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。
附代码
题目背景: 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; }
相关文章推荐
- [NOIP2017模拟]Xor
- 2016.08.19上午【初中部 NOIP普及组 】模拟
- 5368. 【NOIP2017提高A组模拟9.16】为逝去的公主献上的七重樱 单调队列
- [模拟][NOIP2007] 统计数字
- [NOIP2017]时间复杂度(模拟)
- 【NOIP2016提高A组模拟7.15】斐波那契数列(矩阵乘法)
- 【NOIP2013模拟联考12】数数(数位dp||类欧几里得)
- NOIP模拟17.9.22
- 【NOIP2012模拟10.27】比赛
- 【NOIP2012模拟10.25】旅行
- JZOJ5385. 【NOIP2017提高A组模拟9.23】Carry
- 【JZOJ4747】【NOIP2016提高A组模拟9.3】被粉碎的线段树
- 【JZOJ4930】【NOIP2017提高组模拟12.18】C
- 【NOIP普及组】2016年模拟考试(9.3)——笨笨的西瓜种植
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- 【NOIP模拟】Crisis
- 【NOIP2012模拟10.26】雕塑
- 16.9.10 C:3059. 【NOIP2012模拟10.26】雕塑
- 【NOIP2016提高A组模拟9.15】Math
- [JZOJ5395]【NOIP2017提高A组模拟10.6】Count