zoukankan      html  css  js  c++  java
  • trie--- POJ 3764 The xor-longest Path

    The xor-longest Path
    Time Limit: 2000MS   Memory Limit: 65536K
    Total Submissions: 5453   Accepted: 1190

    Description

    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:

                                                                 

    ⊕ 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)

     这道题要求最长的异或路径:就是在树中找两个节点,两个节点间有唯一路径(因为是树),把路径不断做异或,异或完后求最大的。数据是10万,O(n2算法超时

    题目描述:

    给你一棵树,n个节点(n = 100000),n-1条边每条边i都有一个权值wi。

    定义任意两点间的权值为:

    这两点间的路径上的所有边的值的异或。

    比如a点和b点间有i,j,k三条边,那么ab两点间的权值为:wi^wj^wk

    求这个最大的权值。

    /*基本思路:1.因为有(x^z)^(y^z)==x^y,s所以为了求树上任意两点间的x^y的和,我们可以把从根节点开始到每个点的^值存下来(dfs解决,复杂度 O(n)),然后问题就转变为了从这些数中取出两个数字,使他们的异或值最大
      如何在剩下的值中寻找两个数的异或和最大,朴素算法n^2,明显是超时的,---经典解决方法:trie树,边建树的同时边搜索匹配,因为是借助trie比较,复杂度就变为了O(nlogn),就可以过了*/
    #include<iostream>
    using namespace std;
    #include<cstdio>
    #include<cstring>
    #define N 100010
    struct Edge{/*边表*/
        int v,w,last;
    }edge[4*N];
    int head[N]={0},t=0;
    struct Trie{
        int next[2];
    }trie[N<<4];/*trie树*/
    bool visit[N]={false};
    int n,ans=0;
    int value[N]={0},topt=0;/*value数组各结点到结点0的异或长度*/
    void add_edge(int u,int v,int w)
    {
        ++t;
        edge[t].v=v; edge[t].w=w;
        edge[t].last=head[u];
        head[u]=t;
    }
    void dfs(int k,int val)
    {
        visit[k]=true;
        value[k]=val;/*dfs求value数组的过程*/
        for(int l=head[k];l;l=edge[l].last)
        {
            if(!visit[edge[l].v])
            dfs(edge[l].v,val^edge[l].w);
        }
    }
    
    void add_trie(int num)
    {
        int now=0;/*建trie树的过程*/
        for(int i=30;i>=0;--i)
        {
            int a=num&(1<<i)?1:0;/*取出num的二进制位的快速方法,注意这里最好用三目运算符解决,我直接用a=num&(1<<i),虽然结果正确,但是在网上提交总是runtime error*/
            if(!trie[now].next[a])
            trie[now].next[a]=++topt;
            now=trie[now].next[a];
        }
    }
    int find(int num)/*从二进制的第31位到第1位查找最大异或值*/
    {
        int w=0;
        int now=0;
        for(int i=30;i>=0;--i)
        {
            int a=(num&(1<<i))?0:1;/*获取num的二进制数的第i+1位上的数字的非,这样取出异或值才是最大*/
            if(trie[now].next[a])
            {
                w|=(1<<i);
                now=trie[now].next[a];
            }
            else now=trie[now].next[!a];
            
        }
        return w;
    }
    int main()
    {
        while(scanf("%d",&n)==1)
      {
        int u,v,w;
        for(int i=1;i<n;++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);/*对于每个无向图中,每个节点只走一次,不能只建一条有向边,而是应该建两条边,给每一个节点做一个visit数组即可*/
            add_edge(v,u,w);
        }
        dfs(0,0);
        for(int i=0;i<=n-1;++i)
        {
            add_trie(value[i]);/*一边建树*/
            int w=0;
            w=find(value[i]);/*一边查询*/
            ans=max(w,ans);
        }
        printf("%d
    ",ans);
        memset(head,0,sizeof(head));/*对于有多组测试数据的题目,不要忘记每次循环,把所有的量都初始化*/
        memset(value,0,sizeof(value));
        memset(trie,0,sizeof(trie));
        memset(edge,0,sizeof(edge));
        memset(visit,0,sizeof(visit));
        topt=0;t=0;ans=0;n=0;
      }
        return 0;
    }
  • 相关阅读:
    Codeforces Round 546 (Div. 2)
    Codeforces Round 545 (Div. 2)
    Codeforces Round 544(Div. 3)
    牛客小白月赛12
    Codeforces Round 261(Div. 2)
    Codeforces Round 260(Div. 2)
    Codeforces Round 259(Div. 2)
    Codeforces Round 258(Div. 2)
    Codeforces Round 257 (Div. 2)
    《A First Course in Probability》-chaper5-连续型随机变量-随机变量函数的分布
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5475301.html
Copyright © 2011-2022 走看看