【POJ3764】The xor-longest Path Trie树+异或性质

来源:互联网 发布:社交媒体大数据 编辑:程序博客网 时间:2024/04/29 15:21

#include <stdio.h>int main(){puts("转载请注明出处[vmurder]谢谢");puts("网址:blog.csdn.net/vmurder/article/details/43486733");}


题意:

多组数据、

给你一颗树,

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

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


题解:

首先无根树转有根树再在树上跑一遍算出每个点到根的异或和。

然后两点间异或路径长度就是a[i]*a[j]。

因为lca之前那一段都被异或了两次搞没了。


然后求个线性基,然后随便搞搞就可以?可以WA了!

因为那么算哪是简单路径啊,或者说,那特喵的是什么玩意啊。


嗯,写个Trie树,然后详情可以看我这篇博客。

【JDFZOJ】最富有的人 Trie树+异或性质

诶?这篇博客什么也没说?


好吧,我补个题解:

Trie里面记录每个节点权值的二进制串,

比如5,我们不记录“101”,而是记录“00000……000101”


这样Trie树建好了以后我们枚举一个节点,然后用这个节点在Trie树中找它的最长异或路径长度。

这个时候我们在Trie树上跑,每一位都取反以保证这位尽量是1

然后走不了再取同。


所有最长中取个最大值作为答案

这样就在nlogn时间内得到了解。


详见代码

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 101000#define LOGN 32#define T 2#define inf 0x3f3f3f3fusing namespace std;int src[N],n;struct Trie{int son[N*LOGN][T],cnt;void init(){memset(son,0,sizeof son);cnt=0;}void insert(int a){int i,x=0,alp;for(i=31;i>=0;i--){alp=(a>>i)&1;if(!son[x][alp])son[x][alp]=++cnt;x=son[x][alp];}}int find(int a){int i,x=0,alp;int ret=0;for(i=31;i>=0;i--){alp=!((a>>i)&1);ret<<=1;if(son[x][alp]){x=son[x][alp];ret++;}else x=son[x][!alp];}return ret;}}trie;struct KSD{int v,len,next;}e[N<<1];int head[N],cnt;void init(){cnt=0;memset(src,0,sizeof src);memset(head,0,sizeof head);trie.init();}inline void add(int u,int v,int len){e[++cnt].v=v;e[cnt].len=len;e[cnt].next=head[u];head[u]=cnt;}void dfs(int x,int p){int i,v;for(i=head[x];i;i=e[i].next){v=e[i].v;if(v==p)continue;src[v]=src[x]^e[i].len;dfs(v,x);}return ;}int main(){freopen("test.in","r",stdin);int i,j,k;int a,b,c;while(scanf("%d",&n)!=EOF){init();for(i=1;i<n;i++){scanf("%d%d%d",&a,&b,&c);add(a+1,b+1,c),add(b+1,a+1,c);}dfs(1,0);int ans=0;for(i=1;i<=n;i++)trie.insert(src[i]);for(i=1;i<=n;i++)ans=max(ans,trie.find(src[i]));printf("%d\n",ans);}return 0;}



0 0
原创粉丝点击