18.12.17 DSA The xor-longest Path

描述

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.

样例输入

4
0 1 3
1 2 4
1 3 6

样例输出

7

提示

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

  1 #include < algorithm >
  2 #include < cstdio >
  3 #include < cstring >
  4 #include < vector >
  5 using namespace std;
  6 
  7 const int MAXN = 100010;
  8 const int MAXM = 200010;
  9 struct Trie {
 10     Trie *children[2];
 11     int value;
 12 } root, pool[MAXN << 5], *ptr, emptyNode;
 13 // Trie树是一棵二叉树,左孩子表示当前二进制位为0,右孩子表示当前二进制位为1
 14 // 叶子节点额外保存value,表示当前路径对应的数,如根-左-右-右这个节点的value为(011)2=3
 15 
 16 int n;
 17 // 节点个数
 18 
 19 int head[MAXN], succeed[MAXM], vertex[MAXM], weight[MAXM], now;
 20 // head,succeed使用链表保存边表;vertex,weight存每条边的终点以及权值
 21 
 22 int rootXor[MAXN];
 23 // 每个点到根的路径的xor值
 24 
 25 void addEdge(int u, int v, int w) {
 26     // 往链表中添加一条u->v,权值为w的边
 27     ________(1)________
 28     // 新的节点的后继为u节点原来的链表头
 29     vertex[now] = v;
 30     // 新的边的终点为v
 31     weight[now] = w;
 32     // 新的边的权值为w
 33     head[u] = now++;
 34     // 指定u节点新的链表头为now
 35 }
 36 
 37 void readTree() {
 38     // 读入树
 39     memset(head, -1, sizeof head);
 40     now = 0;
 41     for (int i = 0; i < n - 1; i++) {
 42         int u, v, w;
 43         scanf("%d%d%d", &u, &v, &w);
 44         addEdge(u, v, w);
 45         addEdge(v, u, w);
 46     }
 47 }
 48 
 49 void DFS(int x = 0, int father = -1) {
 50     // DFS求出每个点到0号点的路径的xor值,并填到rootXor数组中
 51     // 参数x表示当前递归到的节点,father表示当前点的父亲
 52     for (int now = head[x]; now != -1; now = succeed[now]) {
 53         // 遍历x节点的链表,找到所有x的出边
 54         int y = vertex[now];
 55         int w = weight[now];
 56         // 从x到y有一条权值为w的边
 57         if (________(2)________)
 58             continue;
 59         // 忽略返回父亲的边
 60         rootXor[y] = ________(3)________;
 61         // 计算rootXor[y]的值,为y到0号点的路径的xor值
 62         DFS(y, x);
 63     }
 64 }
 65 
 66 int getNthBit(int value, int nBit) {
 67     return value >> nBit & 1;
 68 }
 69 
 70 void insertTrie(Trie *node, int value, int nBit) {
 71     // 往Trie中插入value
 72     // 当前在node这个节点,处理到value的第nBit个bit
 73     // 如果nBit为-1,说明已经处理完毕,node为叶子节点
 74     if (nBit == -1)
 75         node->value = ________(4)________;
 76     else {
 77         bool bit = ________(5)________;
 78         // bit为0说明当前的节点应为node的左孩子
 79         // bit为1说明当前的节点应为node的右孩子
 80         if (!node->children[bit]) {
 81             node->children[bit] = ptr++;
 82             *node->children[bit] = emptyNode;
 83         }
 84         insertTrie(node->children[bit], value, nBit - 1);
 85     }
 86 }
 87 
 88 void buildTrie() {
 89     // 将所有rootXor[i]插入Trie中
 90     root = emptyNode;
 91     ptr = pool;
 92     for (int i = 0; i < n; i++)
 93         insertTrie(&root, rootXor[i], 30);
 94 }
 95 
 96 int queryTrie(Trie *node, int value, int nBit) {
 97     // 在Trie中查询与value的xor值最大的答案
 98     // 当前在node这个节点,处理到value的第nBit个bit
 99     // 如果nBit为-1,说明已经处理完毕,node为叶子节点
100     if (nBit == -1)
101         return node->value ^ value;
102     else {
103         bool bit = ________(5)________;
104         // 同上
105         if (node->children[!bit])
106             return queryTrie(node->children[!bit], value, nBit - 1);
107         else
108             return queryTrie(node->children[bit], value, nBit - 1);
109     }
110 }
111 
112 int getAns() {
113     // 将所有rootXor[i]在Trie中查询最大的xor答案
114     int ans = 0;
115     for (int i = 0; i < n; i++)
116         ans = max(ans, queryTrie(&root, rootXor[i], 30));
117     return ans;
118 }
119 
120 int main() {
121     while (scanf("%d", &n) == 1) {
122         readTree();
123         DFS();
124         buildTrie();
125         printf("%d\n", getAns());
126     }
127     return 0;
128 }

填空答案:

  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <stack>
  5 #include <string>
  6 #include <math.h>
  7 #include <queue>
  8 #include <stdio.h>
  9 #include <string.h>
 10 #include <set>
 11 #include <vector>
 12 #include <fstream>
 13 #define maxn 400005
 14 #define inf 999999
 15 #define cha 127
 16 using namespace std;
 17 
 18 const int MAXN = 100010;
 19 const int MAXM = 200010;
 20 struct Trie {
 21     Trie *children[2];
 22     int value;
 23 } root, pool[MAXN << 5], *ptr, emptyNode;
 24 // Trie树是一棵二叉树,左孩子表示当前二进制位为0,右孩子表示当前二进制位为1
 25 // 叶子节点额外保存value,表示当前路径对应的数,如根-左-右-右这个节点的value为(011)2=3
 26 
 27 int n;
 28 // 节点个数
 29 
 30 int head[MAXN], succeed[MAXM], vertex[MAXM], weight[MAXM], now;
 31 // head,succeed使用链表保存边表;vertex,weight存每条边的终点以及权值
 32 
 33 int rootXor[MAXN];
 34 // 每个点到根的路径的xor值
 35 
 36 void addEdge(int u, int v, int w) {
 37     // 往链表中添加一条u->v,权值为w的边
 38     succeed[now] = head[u];
 39         // 新的节点的后继为u节点原来的链表头
 40         vertex[now] = v;
 41     // 新的边的终点为v
 42     weight[now] = w;
 43     // 新的边的权值为w
 44     head[u] = now++;
 45     // 指定u节点新的链表头为now
 46 }
 47 
 48 void readTree() {
 49     // 读入树
 50     memset(head, -1, sizeof head);
 51     now = 0;
 52     for (int i = 0; i < n - 1; i++) {
 53         int u, v, w;
 54         scanf("%d%d%d", &u, &v, &w);
 55         addEdge(u, v, w);
 56         addEdge(v, u, w);
 57     }
 58 }
 59 
 60 void DFS(int x = 0, int father = -1) {
 61     // DFS求出每个点到0号点的路径的xor值,并填到rootXor数组中
 62     // 参数x表示当前递归到的节点,father表示当前点的父亲
 63     for (int now = head[x]; now != -1; now = succeed[now]) {
 64         // 遍历x节点的链表,找到所有x的出边
 65         int y = vertex[now];
 66         int w = weight[now];
 67         // 从x到y有一条权值为w的边
 68         if (y==father)
 69             continue;
 70         // 忽略返回父亲的边
 71         rootXor[y] = rootXor[x]^w;
 72         // 计算rootXor[y]的值,为y到0号点的路径的xor值
 73         DFS(y, x);
 74     }
 75 }
 76 
 77 int getNthBit(int value, int nBit) {
 78     return value >> nBit & 1;
 79 }
 80 
 81 void insertTrie(Trie *node, int value, int nBit) {
 82     // 往Trie中插入value
 83     // 当前在node这个节点,处理到value的第nBit个bit
 84     // 如果nBit为-1,说明已经处理完毕,node为叶子节点
 85     if (nBit == -1)
 86         node->value = value;
 87     else {
 88         bool bit = getNthBit(value, nBit);
 89         // bit为0说明当前的节点应为node的左孩子
 90         // bit为1说明当前的节点应为node的右孩子
 91         if (!node->children[bit]) {
 92             node->children[bit] = ptr++;
 93             *node->children[bit] = emptyNode;
 94         }
 95         insertTrie(node->children[bit], value, nBit - 1);
 96     }
 97 }
 98 
 99 void buildTrie() {
100     // 将所有rootXor[i]插入Trie中
101     root = emptyNode;
102     ptr = pool;
103     for (int i = 0; i < n; i++)
104         insertTrie(&root, rootXor[i], 30);
105 }
106 
107 int queryTrie(Trie *node, int value, int nBit) {
108     // 在Trie中查询与value的xor值最大的答案
109     // 当前在node这个节点,处理到value的第nBit个bit
110     // 如果nBit为-1,说明已经处理完毕,node为叶子节点
111     if (nBit == -1)
112         return node->value ^ value;
113     else {
114         bool bit = getNthBit(value,nBit);
115         // 同上
116         if (node->children[!bit])
117             return queryTrie(node->children[!bit], value, nBit - 1);
118         else
119             return queryTrie(node->children[bit], value, nBit - 1);
120     }
121 }
122 
123 int getAns() {
124     // 将所有rootXor[i]在Trie中查询最大的xor答案
125     int ans = 0;
126     for (int i = 0; i < n; i++)
127         ans = max(ans, queryTrie(&root, rootXor[i], 30));
128     return ans;
129 }
130 
131 int main() {
132     while (scanf("%d", &n) == 1) {
133         readTree();
134         DFS();
135         buildTrie();
136         printf("%d\n", getAns());
137     }
138     return 0;
139 }
View Code
posted @ 2018-12-17 17:36  TobicYAL  阅读(383)  评论(0编辑  收藏  举报