zoukankan      html  css  js  c++  java
  • P4551 最长异或路径

    题目描述

    给定一棵 nnn 个点的带权树,结点下标从 111 开始到 NNN 。寻找树中找两个结点,求最长的异或路径。

    异或路径指的是指两个结点之间唯一路径上的所有边权的异或。

    输入输出格式

    输入格式:

    第一行一个整数 NNN ,表示点数。

    接下来 n−1n-1n1 行,给出 u,v,wu,v,wu,v,w ,分别表示树上的 uuu 点和 vvv 点有连边,边的权值是 www 。

    输出格式:

    一行,一个整数表示答案。

    输入输出样例

    输入样例#1: 
    4
    1 2 3
    2 3 4
    2 4 6
    输出样例#1: 
    7

    说明

    最长异或序列是1-2-3,答案是 7 (=3 ⊕ 4)

    数据范围

    1≤n≤100000;0<u,v≤n;0≤w<2311le n le 100000;0 < u,v le n;0 le w < 2^{31}1n100000;0<u,vn;0w<231

    Solution:

      套路题,01trie树+dfs序。

      首先很容易想到树上任意两点路径的异或和在dfs序上直接可以体现出来,于是直接搞出dfs序,然后求出异或前缀和并插入trie树中,最后只需要在trie树中贪心的求一遍每个异或前缀和能与树中异或和异或出的最大值就好了。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=2e5+7;
    int n,a[N],to[N],net[N],w[N],h[N],cnt,op[N];
    int trie[N*31][2],tot,ans;
    
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return f?-a:a;
    }
    
    il void add(int u,int v,int c){to[++cnt]=v,net[cnt]=h[u],w[cnt]=c,h[u]=cnt;}
    
    il void dfs(int u,int lst,int val){
        a[++cnt]=u,op[u]=val;
        for(int i=h[u];i;i=net[i]) if(to[i]!=lst) dfs(to[i],u,w[i]);
        a[++cnt]=u;
    }
    
    il void insert(int a){
        int p=0,x;
        Bor(i,0,30){
            x=(1<<i&a?1:0);
            if(!trie[p][x])trie[p][x]=++tot;
            p=trie[p][x];
        }
    }
    
    il int search(int a){
        int p=0,x,ans=0;
        Bor(i,0,30){
            x=(1<<i&a?0:1);
            if(!trie[p][x]) p=trie[p][x^1];
            else p=trie[p][x],ans+=1<<i;
        }
        return ans;
    }
    
    int main(){
        n=gi();
        int u,v,c;
        For(i,1,n-1) u=gi(),v=gi(),c=gi(),add(u,v,c),add(v,u,c);
        cnt=0;
        dfs(1,-1,0);
        int sum=0;
        For(i,1,cnt) sum^=op[a[i]],insert(sum);
        sum=0;
        For(i,1,cnt) sum^=op[a[i]],ans=max(ans,search(sum));
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    EMV内核使用中的常见问题
    SM2国密证书合法性验证
    WP8.1中C++的winodws运行时组件位移操作的差异
    [源码]Literacy 快速反射读写对象属性,字段
    Vue 单文件元件 — vTabs
    vue-router路径计算问题
    前端跨域新方案尝试
    Vue 单文件原件 — vCheckBox
    JavaScript 功能类 Url.js
    Vue 学习笔记 — 组件初始化
  • 原文地址:https://www.cnblogs.com/five20/p/9484149.html
Copyright © 2011-2022 走看看