最大Xor路径 7.30 T2

来源:互联网 发布:java mysql 编辑:程序博客网 时间:2024/06/05 03:26

题目描述
MT神牛非常喜欢出Xor的题,在WC2011的时候,MT神牛出了一道非常经典的Xor最大路径题。
Bird向MT神牛学习,思考了许多关于Xor路径的问题,有一天,Bird想到了一个问题,给出一个序列,求这个序列的连续子序列的Xor值最大。
如1 3 4 8,最大的Xor子序列当然是3 xor 4 xor 8=15了。
Bird实在太强大了,这个问题怎么能难住他呢?于是Bird又开始思考了,如果是一颗树呢,如何求出这棵带边权的树的一条最大Xor路径呢?但是谁都知道Bird实在太强大了,马上想到了解决这个问题的高效算法,但是Bird总是不愿去机房写代码,于是他把这个easy的问题,交给了你,希望你能尽快帮他写完代码。

输入
第一行,一个整数N,表示一颗树有N个节点,接下来N-1行,每行三个整数a,b,c表示节点a和节点b之间有条权值为c的边

输出
输出仅一行,即所求的带边权树的Xor最大路径。

样例输入
4
1 2 3
1 3 4
1 4 7
样例输出
7

提示
【数据规模】
对于40%的数据,数据退化为一条链
除上述的40%的数据外,还有10%的数据N<=1000
100%的数据满足2<=n<=100000, 1 < a,b<=N,C<=2^31-1

我们先考虑是一条链的情况:

F[i]iiji<jF[j]xorF[i]maxF[i]xorF[j]1<=i,j<=N.

然后我们考虑是树的情况:

类似于链,我们用F[i]表示根节点到i的异或和,显然i->j路径的异或和等价于F[i] xor F[j],这与链的情况无异。所以题目就可以转化为给定N个数,求出这N个数中任意两个数xor的最大值。

具体做法:

在二进制中,越高位有1值越大,而异或运算只影响到当前位,所以越高位能异或成1就把它异或成1,于是我们将所有F[i]转为二进制当做字符串,按从高位到低位的顺序存入一颗字典树中,然后从最高位开始枚举,设当前数为x,当前枚举到二进制中第i位,x的第i位数字为j,当前在字典树中的k号节点,若k节点的j xor 1儿子存在,则当前答案的第i位为1,否则为0。时间复杂度(N*900)。
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#define ll long longusing namespace std;int n,x,y,z,tot,ans;int a[35],head[100005],Next[200005],to[200005],len[200005],f[100005];struct ty{    int Next[2];    void init()    {        memset(Next,-1,sizeof(Next));    }}p[3100005];void dfs(int k,int pre){    for(int i=head[k];i!=-1;i=Next[i])     if(to[i]!=pre)     {        f[to[i]]=f[k]^len[i];        dfs(to[i],k);    }}void add(int x,int y,int z){    tot++;    Next[tot]=head[x];    to[tot]=y;    len[tot]=z;    head[x]=tot;}void work(int x){    int k=0;    while(x>0)     {        k++;        a[k]=x%2;        x=x/2;    }    for(int i=k+1;i<=31;i++) a[i]=0; }void update(){    x=0;    for(int i=31;i>=1;i--)     {        int j=a[i];        if(p[x].Next[j]==-1)         {            tot++;            p[x].Next[j]=tot;            p[tot].init();        }        x=p[x].Next[j];    }}int query(){    x=0;    int s=0;    for(int i=31;i>=1;i--)     {        int j=a[i]^1;        if(p[x].Next[j]==-1)  j=j^1;        if((a[i]^j)==1) s=s+(1<<(i-1));        x=p[x].Next[j];    }    return s;}                int main(){    cin>>n;    for(int i=1;i<=n;i++) head[i]=-1;    for(int i=1;i<n;i++)     {        scanf("%d%d%d",&x,&y,&z);        add(x,y,z);        add(y,x,z);    }    dfs(1,0);    p[0].init();    for(int i=1;i<=n;i++)     {        work(f[i]);        update();    }    for(int i=1;i<=n;i++)     {        work(f[i]);        ans=max(ans,query());    }    cout<<ans;    return 0;}
0 0
原创粉丝点击