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:
⊕ 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\n", ans); } int main() { // freopen("in.txt", "r", stdin); while(~scanf("%d", &n)) { read(); bfs(); solve(); } }