• bzoj1954 The xor-longest path


    Description

     给定一棵n个点的带权树,求树上最长的异或和路径

    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
    1 2 3
    2 3 4
    2 4 6

    Sample Output

    7

    HINT

    The xor-longest path is 1->2->3, which has length 7 (=3 ⊕ 4) 
    注意:结点下标从1开始到N....

     
    因为这道题求的是树上的最大异或和路径。我们知道对于树上路径,要么是一条链,要么是对于一个节点的两个不同的子链。
    我们记录树上每个点到根节点的亦或和。对于每个异或和的二进制建一颗trie树。
    然后贪心,从trie根节点向下,尽量使跑到的边和原本的异或和不同,因为这样它们再次亦或才最大。
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define REP(i,k,n) for(int i=k;i<=n;i++)
    #define in(a) a=read()
    #define MAXN 300010
    using namespace std;
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        for(;!isdigit(ch);ch=getchar())
            if(ch=='-')
                f=-1;
        for(;isdigit(ch);ch=getchar())
            x=x*10+ch-'0';
        return x*f;
    }
    queue <int> Q;
    int n,cnt=0,ans;
    int vis[MAXN],sum[MAXN];
    int tree[6333333][2];
    int total=0,head[MAXN],nxt[MAXN],to[MAXN],val[MAXN];
    inline void adl(int a,int b,int c){
        total++;
        to[total]=b;
        val[total]=c;
        nxt[total]=head[a];
        head[a]=total;
        return ;
    }
    inline void bfs(){
        Q.push(1);
        vis[1]=1;
        while(!Q.empty()){
            int u=Q.front();
            Q.pop();
            for(int e=head[u];e;e=nxt[e])
                if(!vis[to[e]]){
                    vis[to[e]]=1;
                    sum[to[e]]=sum[u]^val[e];
                    Q.push(to[e]);
                }
        }
        return ;
    }
    inline void insert(int x){
        int u=0;
        for(int i=30;i>=0;i--){
            int t=x&(1<<i);
            t=(t>>i);
            if(!tree[u][t])  tree[u][t]=++cnt;
            u=tree[u][t];
        }
        return ;
    }
    inline int query(int x){
        int u=0,tmp=0;
        for(int i=30;i>=0;i--){
            int t=x&(1<<i);
            t=(t>>i);
            if(tree[u][t^1])  u=tree[u][t^1],tmp+=(1<<i);
            else  u=tree[u][t];
        }
        return tmp;
    }
    int main(){
        in(n);
        int a,b,c;
        REP(i,1,n-1) in(a),in(b),in(c),adl(a,b,c),adl(b,a,c);
        bfs();
        REP(i,1,n)  insert(sum[i]);
        REP(i,1,n){
          ans=max(ans,query(sum[i]));
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    黑马程序员面向对象09天1
    一键安装LNMP
    多屏互动技术
    阿里云CentOS 64位解决kernel2.6.32220.13.1.el6.x86_64 has missing requires错误
    listview的onItemClickListener失效
    在阿里云主机上基于CentOS用vsftpd搭建FTP服务器(赚)
    asp.net关于在线支付的实现过程
    C#关闭登录窗体,显示主窗体
    winform 刷新父窗体(转)
    用代码生成器生成的DAL数据访问操作类 基本满足需求了
  • 原文地址:https://www.cnblogs.com/jason2003/p/9747688.html
Copyright © 2020-2023  润新知