• POJ3764 The xor-longest Path(异或/01Trie)


    In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:

    _{xor}length(p)=oplus_{e in p}w(e)

    ⊕ is the xor operator.

    We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?  

    Input

    The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.

    Output

    For each test case output the xor-length of the xor-longest path.

    Sample Input

    4
    0 1 3
    1 2 4
    1 3 6
    

    Sample Output

    7

    Hint

    The xor-longest path is 0->1->2, which has length 7 (=3 ⊕ 4)

    这题有LCA内味了。注意到异或的性质,设d[x]为根节点到x的路径的异或值,则x到y的异或值实际上就是d[x] xor d[y],因为根节点到LCA(x,y)的这段路径自己异或了两次相当于什么都没有变。因此问题转化为从d数组挑选两个数使得其异或值最大,就变成01字典树了。

    坑点:多组输入,记得及时清空数组以及ans,tot等变量,数组开两倍建反向边。略微卡点时间,因此尽量采取快一点的写法和输入输出等。

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #define N 100005
    using namespace std;
    int n,head[N],ver[2*N],Next[2*N],edge[2*N],ttot=0,d[N];
    
    int trie[100005*31][2],tot=1,ans=0;
    void add(int x,int y,int z)
    {
        ver[++ttot]=y,edge[ttot]=z,Next[ttot]=head[x],head[x]=ttot;
    }
    void dfs(int x,int pre,int sum)
    {
        int i;
        for(i=head[x];i;i=Next[i])
        {
            int y=ver[i],z=edge[i];
            if(y==pre) continue;
            d[y]=z^sum;
            dfs(y,x,d[y]);
        }
    }
    int fpow(int a,int b)
    {
        int ans=1;
        for(;b;b>>=1)
        {
            if(b&1) ans=ans*a;
            a=a*a;
        }
        return ans;
    }
    void insert(int x)
    {
        int p=1,k;
        for(k=30;k>=0;k--)
        {
            int temp=x&(1<<k)?1:0;
            if(trie[p][temp]==0) trie[p][temp]=++tot;
            p=trie[p][temp];
        }
    }
    int search(int x)//返回最大的异或值 
    {
        int k,p=1,num=0;
        for(k=30;k>=0;k--)
        {
            int orip=p,temp=x&(1<<k)?1:0;
            p=trie[p][1-temp];//防止p被更改 
            if(p==0) 
            {
                p=trie[orip][temp];//退而求其次
            }
            else
            {
                num+=fpow(2,k);
            }
        }
        return num;
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            memset(head,0,sizeof(head));
            memset(Next,0,sizeof(Next));
            memset(edge,0,sizeof(edge));
            memset(ver,0,sizeof(ver));
            memset(trie,0,sizeof(trie));
            tot=1,ttot=0,ans=0;
            int i;
            for(i=1;i<=n-1;i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
                add(y,x,z);
            } 
            dfs(0,-1,0);
            for(i=0;i<n;i++)
            {
                insert(d[i]);
            }
            for(i=0;i<n;i++)
            {
                ans=max(ans,search(d[i]));
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    PowerDesigner 找不到Identity列的解决方法
    C# DataTable 和List之间相互转换的方法
    解决Win8无法升级.NET Framework 3.5.1 提示错误0x800F0906
    C#虚方法和抽象方法区别
    VS自带WCF测试客户端
    asp.net读取Excel数据
    输出用户的IP地址,并且判断用户的IP地址是否在192.168.1.100 --- 192.168.1.150之间
    验证电子邮箱正则表达式
    用PHP实现冒泡排序将数组$a=array()按照从小到大的方式排序
    打开a.txt文件在文件中最前面加上hello
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/13037408.html
Copyright © 2020-2023  润新知