Luogu4551 最长异或路径

题目链接:戳我

emmmmmmmmmm异或一个数两次等于没有操作对吧。。。所以我们按照前缀的异或和,建一个01trie。。。。。然后之后。。。。。直接在树上贪心地找能和它每一位不一样的数。。。。然后。。。。就没有了吧qwqwq

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
int n,t,cnt=1;
int sum[MAXN],head[MAXN],ch[MAXN*31][2];
int ans=0;
struct Edge{int nxt,to,dis;}edge[MAXN<<1];
inline void add(int from,int to,int dis)
{
    edge[++t].nxt=head[from],edge[t].to=to;
    edge[t].dis=dis,head[from]=t;
}
inline void init(int x,int pre)
{
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==pre) continue;
        sum[v]=sum[x]^edge[i].dis;
        init(v,x);
    }
}
inline void insert(int x)
{
    int now=0;
    for(int i=30;i>=0;i--)
    {
        int v=(x&(1<<i))>>i;
        if(!ch[now][v]) ch[now][v]=++cnt;
        now=ch[now][v];
    }
}
inline int get_ans(int x)
{
    int now=0,cur_ans=0,v;
    for(int i=30;i>=0;i--)
    {
        v=(x&(1<<i))>>i;
        if(ch[now][!v]) 
            now=ch[now][!v],cur_ans+=(1<<i);
        else now=ch[now][v];
    }
    return cur_ans;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    freopen("ce.out","w",stdout);
    #endif
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w),add(v,u,w);
    }
    init(1,1);
    for(int i=1;i<=n;i++) insert(sum[i]);
    for(int i=1;i<=n;i++) ans=max(ans,get_ans(sum[i]));
    printf("%d\n",ans);
    return 0;
}
posted @ 2019-03-05 21:09  风浔凌  阅读(171)  评论(0编辑  收藏  举报