zoukankan      html  css  js  c++  java
  • The XOR-longest Path(Bzoj1954)

    试题描述
    给定一棵 n 个点的带权树,求树上最长的异或和路径。
    输入
    多组数据。
    每组数据第一行一个整数 n(1≤n≤10^5),接下来 n−1 行每行三个整数 u,v,w,表示 u,v 之间有一条长度为 w 的边。(0≤u,v<n,0≤w<2^31)
    输出
    对于每组数据输出答案。
    输入示例
    4
    1 2 3
    2 3 4
    2 4 6
    输出示例
    7

    论一个人能sb到什么程度

    写了半天发现多写了一个取反QAQ

    日常被卡,这题的数据范围好像给错了

    然后既然是关于异或的,我们肯定要想到Trie,将每条路径的异或和求出(首位补零)

    然后在Trie树上跑一遍,尽量选择与它的当前为不同的

    相加就可以了

    下面给出代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    inline int rd(){
        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;
    }
    inline void write(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    int n;
    int trie[1000006][2];
    int tot=1;
    int head[1000006];
    int nxt[1000006];
    int to[1000006];
    int total=0;
    int v[1000006];
    void add(int x,int y,int z){//邻接表连边 
        total++;
        to[total]=y;
        v[total]=z;
        nxt[total]=head[x];
        head[x]=total;
        return ;
    }
    int a[1000006];
    void pre(int x){
        int c=1;
        for(int i=0;i<=30;i++){
            a[i]=x&1;
            x>>=1;
        }
        reverse(a,a+31);//正序建树  补零 
        for(int i=0;i<=30;i++){
            int s=a[i];
            if(!trie[c][s]) trie[c][s]=++tot;
            c=trie[c][s];
        }
        return ;
    }
    int num[1000006];
    void dfs(int x,int fa){//计算每一条路径的异或和 
        for(int e=head[x];e;e=nxt[e]){
            if(to[e]==fa) continue;
            num[to[e]]=num[x]^v[e];
            dfs(to[e],x);
        }
        return ;
    }
    int check(int x){
        int c=1;
        int sum=0;
        for(int i=0;i<=30;i++){
            a[i]=x&1;
            x>>=1;
        }
        reverse(a,a+31);
        for(int i=0;i<=30;i++){
            int s=a[i];
            if(trie[c][!s]){//尽量选择不同的 让异或和最大 
                c=trie[c][!s];
                sum+=(1<<30-i);
            }
            else c=trie[c][s];
        }
        return sum;
    }
    int main(){
        while(cin>>n){
            memset(trie,0,sizeof(trie));
            memset(num,0,sizeof(num));
            memset(head,0,sizeof(head));//赋初值 
            total=0;
            tot=1;
            for(int i=1;i<n;i++){
                int x=rd(),y=rd(),z=rd();
                add(x,y,z);
                add(y,x,z);
            }
            dfs(1,0);
            for(int i=1;i<=n;i++) pre(num[i]);
            int ans=0;
            for(int i=1;i<=n;i++) ans=max(ans,check(num[i]));//取最大值 
            printf("%d",ans);
        }
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    gson和fastjson
    Hive和HBase的区别
    mac 比较两个文件
    mysql 查找在另一张表不存在的数据
    mysql 根据一张表更新另一张表
    shell调试
    目标
    百度在线面试总结
    20170109| javascript记录
    php-fpm问题
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9720527.html
Copyright © 2011-2022 走看看