2018.10.26 洛谷P4551 最长异或路径(01trie)

时间:2023-03-08 17:45:05
2018.10.26 洛谷P4551 最长异或路径(01trie)

传送门

直接把每个点到根节点的异或距离插入01trie。

然后枚举每个点在01trie上匹配来更新答案就行了。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
const int N=1e5+5;
int son[N*32][2],rt=1,n,W,first[N],dis[N],cnt=0,tot=1,ans=0;
struct edge{int v,next,w;}e[N<<1];
inline void addedge(int u,int v,int w){e[++cnt].v=v,e[cnt].next=first[u],e[cnt].w=w,first[u]=cnt;}
inline void add(int u,int v,int w){addedge(u,v,w),addedge(v,u,w);}
void dfs(int p,int fa,int sum){
    dis[p]=sum;
    for(int i=first[p];i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)continue;
        dfs(v,p,sum^e[i].w);
    }
}
inline void insert(int val){
    int p=rt;
    for(int i=31;~i;--i){
        int tmp=(val>>i)&1;
        if(!son[p][tmp])son[p][tmp]=++tot;
        p=son[p][tmp];
    }
}
inline int query(int val){
    int ret=0,p=rt;
    for(int i=31;~i;--i){
        int tmp=(val>>i)&1;
        ret<<=1;
        if(son[p][tmp^1])++ret,p=son[p][tmp^1];
        else p=son[p][tmp];
    }
    return ret;
}
int main(){
    n=read();
    for(int i=1,u,v,w;i<n;++i)u=read(),v=read(),w=read(),add(u,v,w);
    dfs(1,0,0);
    for(int i=1;i<=n;++i)insert(dis[i]);
    for(int i=1;i<=n;++i)ans=max(ans,query(dis[i]));
    printf("%d",ans);
    return 0;
}