zoukankan      html  css  js  c++  java
  • 树上异或和最大

    http://poj.org/problem?id=3764

    题意:求上任意两点的边权异或最大值。

    解法:dfs遍历树的同时将异或值加入01字典树中,同时查询最大异或值。

    这样为什么就能保证你所求的结果对应的路径是连续的呢?考虑三种情况:


    1.深搜的两条路径一个包含在另一个中,这样一异或,公共的部分的值变成 0 了,剩下的部分是连续的。


    2.深搜的两条路径部分重叠,同理,异或后公共的部分变成 0 了,由于是对边权的异或,剩下的部分仍然连续。


    3.深搜的两条路径不重叠,但是两条路径肯定有公共的点——根节点,也是连续的。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <string.h>
    #include <vector>
    #define ME(x , y) memset(x , y , sizeof(x))
    #define SF(n) scanf("%d" , &n)
    #define rep(i , n) for(int i = 0 ; i < n ; i ++)
    #define INF  0x3f3f3f3f
    #define mod 1000000007
    #define PI acos(-1)
    using namespace std;
    typedef unsigned long long ll ;
    const int N = 100009;
    int tree[N*32][2] , vis[N*32] , tol;
    int head[N] , cnt;
    int v[N];
    int ans ;
    
    struct node{
        int to , next , w ;
    }a[N*2];
    
    void add(int u , int v , int w)
    {
        a[cnt].to = v ;
        a[cnt].next = head[u];
        a[cnt].w = w ;
        head[u] = cnt++;
    }
    
    void insert(int x)
    {
        int u = 0 ;
        for(int i = 31 ; i >= 0 ; i--)
        {
            int p = (x >> i) & 1;
            if(!tree[u][p]) tree[u][p] = ++tol;
            u = tree[u][p];
        }
        vis[u] = x ;
    }
    int research(int x)
    {
        int u = 0 ;
        for(int i = 31 ; i >= 0 ; i--)
        {
            int p = (x >> i) & 1 ;
            if(tree[u][p^1]) u = tree[u][p^1];
            else u = tree[u][p];
        }
        return vis[u] ^ x ;
    }
    
    void dfs(int u , int val)
    {
        v[u] = 1 ;
        insert(val);
        for(int i = head[u] ; i != -1 ; i = a[i].next)
        {
            int vv = a[i].to ;
            if(v[vv]) continue ;
            ans = max(ans , research(val ^ a[i].w));
            dfs(vv, val^a[i].w);
        }
    }
    
    void init()
    {
        memset(vis , 0 , sizeof(vis));
        memset(tree , 0 , sizeof(tree));
        memset(v , 0 , sizeof(v));
        memset(head , -1 , sizeof(head));
        cnt = 0 ;
        tol = 0 ;
        ans = 0 ;
    }
    
    int main()
    {
        int n ;
        while(~scanf("%d" , &n))
        {
            init();
            for(int i = 0 ; i < n - 1 ; i++)
            {
                int u , v , w ;
                scanf("%d%d%d" , &u , &v , &w);
                add(u , v , w);
                add(v , u , w);
            }
            dfs(0  , 0);
            cout << ans << endl ;
        }
    
        return 0;
    }
    
  • 相关阅读:
    Jquery事件
    基础:装箱和拆箱...
    navicat编辑表的作用
    谷歌浏览器preview展示问题
    @Scheduled并行执行
    spring异步执行方法线程池的配置
    dubbo的ExceptionFilter异常处理
    dubbo异常处理
    idea设置启动jvm参数
    前后端分离走本地代码Charles的使用
  • 原文地址:https://www.cnblogs.com/nonames/p/12227502.html
Copyright © 2011-2022 走看看