P4551 最长异或路径
Posted five20
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4551 最长异或路径相关的知识,希望对你有一定的参考价值。
题目描述
给定一棵 nnn 个点的带权树,结点下标从 111 开始到 NNN 。寻找树中找两个结点,求最长的异或路径。
异或路径指的是指两个结点之间唯一路径上的所有边权的异或。
输入输出格式
输入格式:第一行一个整数 NNN ,表示点数。
接下来 n−1n-1n−1 行,给出 u,v,wu,v,wu,v,w ,分别表示树上的 uuu 点和 vvv 点有连边,边的权值是 www 。
输出格式:一行,一个整数表示答案。
输入输出样例
输入样例#1:
4
1 2 3
2 3 4
2 4 6
输出样例#1:
7
说明
最长异或序列是1-2-3,答案是 7 (=3 ⊕ 4)
数据范围
1≤n≤100000;0<u,v≤n;0≤w<2311le n le 100000;0 < u,v le n;0 le w < 2^{31}1≤n≤100000;0<u,v≤n;0≤w<231
Solution:
套路题,01trie树+dfs序。
首先很容易想到树上任意两点路径的异或和在dfs序上直接可以体现出来,于是直接搞出dfs序,然后求出异或前缀和并插入trie树中,最后只需要在trie树中贪心的求一遍每个异或前缀和能与树中异或和异或出的最大值就好了。
代码:
1 #include<bits/stdc++.h> 2 #define il inline 3 #define ll long long 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) 6 using namespace std; 7 const int N=2e5+7; 8 int n,a[N],to[N],net[N],w[N],h[N],cnt,op[N]; 9 int trie[N*31][2],tot,ans; 10 11 il int gi(){ 12 int a=0;char x=getchar();bool f=0; 13 while((x<‘0‘||x>‘9‘)&&x!=‘-‘)x=getchar(); 14 if(x==‘-‘)x=getchar(),f=1; 15 while(x>=‘0‘&&x<=‘9‘)a=(a<<3)+(a<<1)+(x^48),x=getchar(); 16 return f?-a:a; 17 } 18 19 il void add(int u,int v,int c){to[++cnt]=v,net[cnt]=h[u],w[cnt]=c,h[u]=cnt;} 20 21 il void dfs(int u,int lst,int val){ 22 a[++cnt]=u,op[u]=val; 23 for(int i=h[u];i;i=net[i]) if(to[i]!=lst) dfs(to[i],u,w[i]); 24 a[++cnt]=u; 25 } 26 27 il void insert(int a){ 28 int p=0,x; 29 Bor(i,0,30){ 30 x=(1<<i&a?1:0); 31 if(!trie[p][x])trie[p][x]=++tot; 32 p=trie[p][x]; 33 } 34 } 35 36 il int search(int a){ 37 int p=0,x,ans=0; 38 Bor(i,0,30){ 39 x=(1<<i&a?0:1); 40 if(!trie[p][x]) p=trie[p][x^1]; 41 else p=trie[p][x],ans+=1<<i; 42 } 43 return ans; 44 } 45 46 int main(){ 47 n=gi(); 48 int u,v,c; 49 For(i,1,n-1) u=gi(),v=gi(),c=gi(),add(u,v,c),add(v,u,c); 50 cnt=0; 51 dfs(1,-1,0); 52 int sum=0; 53 For(i,1,cnt) sum^=op[a[i]],insert(sum); 54 sum=0; 55 For(i,1,cnt) sum^=op[a[i]],ans=max(ans,search(sum)); 56 cout<<ans; 57 return 0; 58 }
以上是关于P4551 最长异或路径的主要内容,如果未能解决你的问题,请参考以下文章