Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 5646   Accepted: 1226

Description

In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:

Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值

⊕ is the xor operator.

We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?  

Input

The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u and v of length w.

Output

For each test case output the xor-length of the xor-longest path.

Sample Input

4
0 1 3
1 2 4
1 3 6

Sample Output

7

Hint

The xor-longest path is 0->1->2, which has length 7 (=3 ⊕ 4)

题意:给出一颗n个节点的边权树,求一条路径(u,v),使得路径上的边的权值异或值最大

思路:我们可以先0为根,求出其他节点i到根的路径的边权异或值d[i],对于u,v之间路径的边权异或结果就是d[u]^d[v], 那么问题转化为给出n个数,求任意两个异或的最大值

把每一个数以二进制形式从高位到低位插入trie中,然后依次枚举每个数,在trie中贪心,即当前为0则向1走,为1则向0走。

一开始写动态分配节点的trie一直tle。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 100005;

int n;
struct Edge {
    int v, w, nex;
    Edge() {}
    Edge(int v, int w, int nex) : v(v), w(w), nex(nex) {}
};
Edge e[N << 1];
int head[N], tot;
void add(int u, int v, int w) {
    e[tot] = Edge(v, w, head[u]);
    head[u] = tot++;
}
void read() {
    memset(head, -1, sizeof head);
    tot = 0;
    int u, v, w;
    for(int i = 1; i < n; ++i) {
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w);
        add(v, u, w);
    }
}
int d[N], vis[N];
void bfs() {
    queue<int> que;
    que.push(0);
    d[0] = 0;
    memset(vis, 0, sizeof vis);
    int u, v, w;
    vis[0] = 1;
    while(!que.empty()) {
        u = que.front(); que.pop();
        for(int i = head[u]; ~i; i = e[i].nex) {
            v = e[i].v; w = e[i].w;
            if(vis[v]) continue;
            d[v] = d[u] ^ w;
            vis[v] = 1;
            que.push(v);
        }
    }
}
int ch[N * 32][2];
struct Trie {
    int sz;
    Trie() { sz = 1; memset(ch[0], 0, sizeof ch[0]); }
    void _insert(int bs[]) {
        int u = 0;
        for(int i = 30; i >= 0; --i) {
            int c = bs[i];
            if(!ch[u][c]) {
                memset(ch[sz], 0, sizeof ch[sz]);
                ch[u][c] = sz++;
            }
            u = ch[u][c];
        }
    }
    int _search(int bs[]) {
        int u = 0, ans = 0;
        for(int i = 30; i >= 0; --i) {
            int c = bs[i];
            if(c == 1) {
                if(ch[u][0]) { ans += (1 << (i)); u = ch[u][0]; }
                else u = ch[u][1];
            }else {
                if(ch[u][1]) { ans += (1 << (i)); u = ch[u][1]; }
                else u = ch[u][0];
            }
        }
        return ans;
    }
};

int ans;
int b[35];
void get(int x) {
    int ls = 0;
    memset(b, 0, sizeof b);
    while(x) {
        b[ls++] = x % 2;
        x >>= 1;
    }
}
void solve() {
    Trie mytrie;
    ans = 0;
    for(int i = 0; i < n; ++i) {
        get(d[i]);
        mytrie._insert(b);
        ans = max(ans, mytrie._search(b));
    }
    printf("%d
", ans);
}
int main() {
   // freopen("in.txt", "r", stdin);
    while(~scanf("%d", &n)) {
        read();
        bfs();
        solve();
    }
}
View Code