The xor-longest Path

来源:互联网 发布:java开发者社区 编辑:程序博客网 时间:2024/05/14 19:42

The xor-longest Path

  • 查看
  • 提交
  • 统计
  • 提问
总时间限制: 
2000ms 
内存限制: 
65536kB
描述

In an edge-weighted tree, the xor-length of a path pis 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?  

输入

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.

输出
For each test case output the xor-length of the xor-longest path.
样例输入
40 1 31 2 41 3 6
样例输出
7
提示

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


#include<algorithm>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int MAXN = 100010;const int MAXM = 200010;struct Trie {Trie *children[2];int value;} root, pool[MAXN << 5], *ptr, emptyNode;// Trie树是一棵二叉树,左孩子表示当前二进制位为0,右孩子表示当前二进制位为1// 叶子节点额外保存value,表示当前路径对应的数,如根-左-右-右这个节点的value为(011)2=3int n;// 节点个数int head[MAXN], succeed[MAXM], vertex[MAXM], weight[MAXM], now;// head,succeed使用链表保存边表;vertex,weight存每条边的终点以及权值int rootXor[MAXN];// 每个点到根的路径的xor值void addEdge(int u, int v, int w) {// 往链表中添加一条u->v,权值为w的边succeed[now] = head[u];// 新的节点的后继为u节点原来的链表头vertex[now] = v;// 新的边的终点为vweight[now] = w;// 新的边的权值为whead[u] = now++;// 指定u节点新的链表头为now}void readTree() {// 读入树memset(head, -1, sizeof head);now = 0;for (int i = 0; i < n - 1; i++) {int u, v, w;scanf("%d%d%d", &u, &v, &w);addEdge(u, v, w);addEdge(v, u, w);}}void DFS(int x = 0, int father = -1) {// DFS求出每个点到0号点的路径的xor值,并填到rootXor数组中// 参数x表示当前递归到的节点,father表示当前点的父亲for (int now = head[x]; now != -1; now = succeed[now]) {// 遍历x节点的链表,找到所有x的出边int y = vertex[now];int w = weight[now];// 从x到y有一条权值为w的边if (y == father)continue;// 忽略返回父亲的边rootXor[y] = rootXor[x] ^ w;// 计算rootXor[y]的值,为y到0号点的路径的xor值DFS(y, x);}}int getNthBit(int value, int nBit) {return value >> nBit & 1;}void insertTrie(Trie *node, int value, int nBit) {// 往Trie中插入value// 当前在node这个节点,处理到value的第nBit个bit// 如果nBit为-1,说明已经处理完毕,node为叶子节点if (nBit == -1)node->value = value;else {bool bit = getNthBit(value, nBit);// bit为0说明当前的节点应为node的左孩子// bit为1说明当前的节点应为node的右孩子if (!node->children[bit]) {node->children[bit] = ptr++;*node->children[bit] = emptyNode;}insertTrie(node->children[bit], value, nBit - 1);}}void buildTrie() {// 将所有rootXor[i]插入Trie中root = emptyNode;ptr = pool;for (int i = 0; i < n; i++)insertTrie(&root, rootXor[i], 30);}int queryTrie(Trie *node, int value, int nBit) {// 在Trie中查询与value的xor值最大的答案// 当前在node这个节点,处理到value的第nBit个bit// 如果nBit为-1,说明已经处理完毕,node为叶子节点if (nBit == -1)return node->value ^ value;else {bool bit = getNthBit(value, nBit);// 同上if (node->children[!bit])return queryTrie(node->children[!bit], value, nBit - 1);elsereturn queryTrie(node->children[bit], value, nBit - 1);}}int getAns() {// 将所有rootXor[i]在Trie中查询最大的xor答案int ans = 0;for (int i = 0; i < n; i++)ans = max(ans, queryTrie(&root, rootXor[i], 30));return ans;}int main() {while (scanf("%d", &n) == 1) {readTree();DFS();buildTrie();printf("%d\n", getAns());}return 0;}


原创粉丝点击