【题目链接】:
【题意】
请输出树上两个点的异或路径 的最大值。
【题解】
这个题目,y总说过怎么做之后,简直就是醍醐灌顶了。
我们知道Xor路径,我们从根结点处理所有结点的 到根结点的异或和,我们想要两个点的异或路径。
其实就是利用根结点 到两个点 异或和 。因为LCA到根结点异或了两遍,所以答案就保留了异或路径的部分。
其实这个题目就是Xor——pair的变种。
处理从根结点出发的所有结点的位置的异或值。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N = 1e5 + 100 ; 6 int Son[N*31][2]; 7 typedef struct Edge{ 8 int To , next , w ; 9 }Edge ; 10 Edge e[N<<1]; 11 int Head[N],cnt,Dis[N],idx; 12 void Init(){ 13 memset( Head , -1 ,sizeof Head ); 14 cnt = idx = 0 ; 15 } 16 void Add_edge ( int u, int v ,int w ){ 17 e[cnt] = Edge { v , Head[u] , w }; 18 Head[u] = cnt ++ ; 19 } 20 21 void dfs(int u,int Fa,int w ){ 22 Dis[u] = w ; 23 for(int i = Head[u] ; ~i ; i = e[i].next){ 24 int To = e[i].To; 25 if( To == Fa ) continue ; 26 dfs( To , u , w ^ e[i].w ); 27 } 28 } 29 30 void Insert ( int x ){ 31 int p = 0 ; 32 for (int i=30;~i;i--){ 33 int t = x >> i & 1 ; 34 if( !Son[p][t] ) 35 Son[p][t] = ++idx ; 36 p = Son[p][t] ; 37 } 38 } 39 int Query(int x ){ 40 int p = 0 ,res = 0; 41 for(int i=30;~i;i--){ 42 int t = x >> i & 1 ; 43 if( Son[p][t^1] ){ 44 res += 1 << i ; 45 p = Son[p][t^1]; 46 }else{ 47 p = Son[p][t] ; 48 } 49 } 50 return res ; 51 } 52 int main() 53 { 54 Init(); 55 int n ; 56 scanf("%d",&n); 57 for(int i=1,u,v,w;i<n;i++){ 58 scanf("%d%d%d",&u,&v,&w); 59 Add_edge( u , v , w ); 60 Add_edge( v , u , w ); 61 } 62 dfs( 1 , -1 , 0 ) ; 63 /* 64 for(int i=1;i<=n;i++){ 65 printf("###%d###\n",Dis[i]); 66 } 67 */ 68 for(int i=1;i<=n;i++){ 69 Insert( Dis[i] ); 70 } 71 int res = 0; 72 for(int i=1;i<=n;i++){ 73 res = max( res , Query(Dis[i] ) ); 74 } 75 printf("%d\n",res) ; 76 return 0 ; 77 }
原文地址:https://www.cnblogs.com/Osea/p/11366907.html
时间: 2024-10-02 19:20:56