POJ 3764 (异或+字典树)

Posted 我不吃饼干呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3764 (异或+字典树)相关的知识,希望对你有一定的参考价值。

早就听过用字典树求异或最大值,然而没做过。发现一碰到异或的题就GG,而且因为以前做过的一道类似的题(事实上并不类似)限制了思路,蠢啊= =。

 

题意:一棵带权的树,求任意两点间路径异或的最大值。

题解:设xor(a,b)是求a,b间路径的异或值,那么xor(a,b)=xor(root,a)^xor(root,b)。因为如果LCA(a,b)==root时结论显然成立,不然的话就会有重复走过的部分,但是异或有性质x^x=0,所以LCA(a,b)!=root结论依然成立。

这样题目就很简单了。对每一个xor(root,i)(0<i<n)建立trie,然后对每一个xor(root,i)在trie查询最大值就好了。

 

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#define pk printf("lalala");
#define ppp(x) printf("%d\n", x)
using namespace std;
#define PI acos(-1.0)
#define EXP exp(1.0)
#define EPS 1E-6
#define clr(x,c) memset(x,c,sizeof(x))


const int KIND = 2;
const int MAXN = 5000005;
const int N = 100005;
int cnt_node;

struct node{
    node* nt[KIND];
    void init(){
        memset(nt, 0, sizeof(nt));
    }
} Heap[MAXN];
node *root;
int Xor[N];

inline node* new_node()
{
    Heap[cnt_node].init();
    return &Heap[cnt_node++];
}

void insert(node* root, int *str)
{
    for(int i = 0; i <= 30; ++i){
        int ch = str[i];
        if(root->nt[ch] == NULL)
            root->nt[ch] = new_node();
        root = root->nt[ch];
    }
}

int count(node* root, int *str)
{
    int ans = 0;
    for(int i = 0; i <= 30; ++i){
        int ch = str[i];
        int need = (ch ^ 1);
        if(root->nt[need] == NULL) {
            root = root->nt[ch];
        } else {
            root = root->nt[need];
            ans += (1 << (30 - i));
        }
    }
    return ans;
}

struct Edge {
    int to;
    int w;
    int next;
} edge[N * 2];

int cnt_edge;
int head[N];

void add_edge(int u, int v, int w)
{
    edge[cnt_edge].to = v;
    edge[cnt_edge].w = w;
    edge[cnt_edge].next = head[u];
    head[u] = cnt_edge++;
}

void dfs(int u, int fa, int val)
{
    Xor[u] = val;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        int w = edge[i].w;
        if (v == fa) continue;
        dfs(v, u, val^w);
    }
}


int str[N][40];

int main()
{
    int n;
    while (~scanf("%d",&n)) {
        clr(head, -1);
        cnt_edge = 0;
        cnt_node = 0;
        root = new_node();
        int u, v, w;
        for (int i = 1; i < n; ++i) {
            scanf("%d%d%d",&u, &v, &w);
            add_edge(u, v, w);
            add_edge(v, u, w);
        }
        dfs(0, -1, 0);
        //for (int i = 0; i < n; ++i) printf("%d ", Xor[i]); printf("\n");
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            int idx = 0;
            for (int b = 30; b >= 0; --b) {
                str[i][idx++] = Xor[i] & (1 << b) ? 1 : 0;
            }
            //for (int j = 0; j < idx; ++j) printf("%d ", str[i][j]); printf("\n");
            insert(root, str[i]);
        }
        for (int i = 0; i < n; ++i) {
            ans = max(ans, count(root, str[i]));
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

以上是关于POJ 3764 (异或+字典树)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3764 The xor-longest Path ( 字典树求异或最值 && 异或自反性质 && 好题好思想)

p4551(poj3764) 最长异或路径

POJ3764 The xor-longest Path

POJ3764 The xor-longest Path

poj 3764 字典树

POJ 3764 - The xor-longest Path - [DFS+字典树变形]