码迷,mamicode.com
首页 > 其他好文 > 详细

树上异或和最大

时间:2020-01-22 01:20:18      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:包含   research   const   algo   cto   space   遍历   ret   clu   

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;
}

树上异或和最大

标签:包含   research   const   algo   cto   space   遍历   ret   clu   

原文地址:https://www.cnblogs.com/nonames/p/12227502.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!