最长异或路径

题目描述

给定一棵n个点的带权树,结点下标从1开始到N。寻找树中找两个结点,求最长的异或路径。

异或路径指的是指两个结点之间唯一路径上的所有边权的异或。

输入格式

第一行一个整数NN,表示点数。

接下来 n-1行,给出u,v,w ,分别表示树上的 u 点和 v 点有连边,边的权值是 w。

输出格式

一行,一个整数表示答案。


一个智障题,我昨天还觉得:

啊,好难啊~我还要接着看trie吗

世界已经缺爱了

QAQ

 

 

然鹅

你统计出每个点到跟根节点的路径异或值+01trie就好了

就这样

#include<bits/stdc++.h>
#define re return
#define ll long long
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define inc(i,l,r) for(int i=l;i<=r;++i)

using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=100005;
int n,m,tot,k,tr[maxn*31][2],hd[maxn],yh[maxn];

struct node{
    int to,nt,val;
}e[maxn<<1];
inline void add(int x,int y,int z)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;
}
inline void build(int x)
{
    int now=0;
    for(int i=31;~i;--i)
    {
        int t=x>>i&1;
        if(!tr[now][t])
        tr[now][t]=++tot;
        now=tr[now][t];
    }
}

ll ans=0;
inline void find(int x)
{
    int now=0;
    ll ret=0;
    for(int i=31;~i;--i)
    {
        int t=x>>i&1;
        if(!tr[now][t^1])
        now=tr[now][t];
        else
        {
            ret+=1<<i;
            now=tr[now][t^1];
        }
    }
    ans=max(ans,ret);
}

inline void dfs(int x,int pre) 
{
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(v==pre)continue;
        yh[v]=yh[x]^e[i].val;
        dfs(v,x);
    }
    build(yh[x]);
}
int main()
{
    int x,y,z;
    rd(n);
    inc(i,1,n-1)
    {
        rd(x),rd(y),rd(z);
        add(x,y,z);
    }
    dfs(1,0);
    inc(i,1,n)find(yh[i]); 
    
    printf("%lld",ans);
}

 

 

posted @ 2019-08-20 20:41  凉如水  阅读(313)  评论(0编辑  收藏  举报