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;
}
时间: 2024-11-06 15:18:13

POJ 3764 (异或+字典树)的相关文章

poj 2503:Babelfish(字典树,经典题,字典翻译)

Babelfish Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 30816   Accepted: 13283 Description You have just moved from Waterloo to a big city. The people here speak an incomprehensible dialect of a foreign language. Fortunately, you have

poj 3630 Phone List (字典树 +静态字典树)

Phone List Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22235   Accepted: 6885 Description Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let's say the phone catalogu

POJ训练计划_Colored Sticks(字典树+判断欧拉通路)

解题报告 http://blog.csdn.net/juncoder/article/details/38236333 题目传送门 题意: 问给定一堆的棒,两端有颜色,相同的颜色的棒可以头尾相接,能否连在一条直线. 思路: 把每一根棒两端看成两个点,之间连着线,判断这样的一个图中是否有欧拉通路 欧拉通路: 在联通无向图中,经过G的每一条边一次并且仅有一次的路径为欧拉通路. 求欧拉通路的充分条件:图为联通图,并且仅有两个奇度数的结点或无奇度结点. #include <queue> #includ

POJ 2513 Colored Sticks(字典树+并查集连通性+欧拉回路)

题目地址:POJ 2513 刚开始没想到字典树,用的map函数一直TLE,由于上一次的签到题由于没想到字典树而卡了好长时间的深刻教训,于是过了不久就想起来用字典树了,(为什么是在TLE了5次之后..T^T)然后把map改成了字典树,然后就过了. 这题居然不知不觉的用上了欧拉回路..其实当时我是这样想的..因为相互接触的必须要相同,所以除了两端外,其他的都是两两相同的,所以除了两端的颜色外其他的的个数必须为偶数.然后两端的可能相同可能不相同,相同的话,说明所有的都是偶数个数了,不相同的话那就只有这

D. Vasiliy&#39;s Multiset 异或字典树

D. Vasiliy's Multiset time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output Author has gone out of the stories about Vasiliy, so here is just a formal task description. You are given q queries a

POJ 2503 Babelfish(字典树)

题目链接:http://poj.org/problem?id=2503 题意:翻译单词,若在词典中找不到则输出eh. 思路:裸的字典树. 代码: #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <string> #include <vector> using

poj 1204 Word Puzzles(字典树)

题目链接:http://poj.org/problem?id=1204 思路分析:由于题目数据较弱,使用暴力搜索:对于所有查找的单词建立一棵字典树,在图中的每个坐标,往8个方向搜索查找即可: 需要注意的是查找时不能匹配了一个单词就不在继续往该方向查找,因为在某个坐标的某个方向上可能会匹配多个单词,所以需要一直 查找直到查找到该方向上最后一个坐标: 代码如下: #include <cstdio> #include <cstring> #include <iostream>

POJ 2408 - Anagram Groups - [字典树]

题目链接:http://poj.org/problem?id=2408 World-renowned Prof. A. N. Agram's current research deals with large anagram groups. He has just found a new application for his theory on the distribution of characters in English language texts. Given such a text

POJ 2418 Hardwood Species(字典树)

Hardwood Species Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 20085   Accepted: 7911 Description Hardwoods are the botanical group of trees that have broad leaves, produce a fruit or nut, and generally go dormant in the winter. Ameri