标签:
题目链接:http://poj.org/problem?id=3764
题目大意是在树上求一条路径,使得xor和最大。
由于是在树上,所以两个结点之间应有唯一路径。
而xor(u, v) = xor(0, u)^xor(0, v)。
所以如果预处理出0结点到所有结点的xor路径和,问题就转换成了求n个数中取出两个数,使得xor最大。
这个之前用字典树处理过类似问题。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <string> #define LL long long using namespace std; const int maxN = 100005; //求n个数中取出两个数能xor的最大值 //Trie Tree字典树 //len*n, len为数的二进制最大长度 const int len = 31;//len表示数的二进制最大长度 struct Trie { int next[2]; }tree[maxN*len]; int cntTree; void initTree() { cntTree = 0; memset(tree, -1, sizeof(tree)); } void add(int x) { int now = 0; bool k; for (int i = len; i >= 0; i--) { k = x&(1<<i); if (tree[now].next[k] == -1) tree[now].next[k] = ++cntTree; now = tree[now].next[k]; } } //返回当前数中能和x合成最大数的数 int query(int x) { int v = 0, now = 0; bool k; for (int i = len; i >= 0; i--) { k = x&(1<<i); if (tree[now].next[!k] != -1) k = !k; v = v|(k<<i); now = tree[now].next[k]; } return v; } //链式前向星 struct Edge { int to, next; int val; }edge[maxN*2]; int head[maxN], cnt; void addEdge(int u, int v, int w) { edge[cnt].to = v; edge[cnt].next = head[u]; edge[cnt].val = w; head[u] = cnt; cnt++; } void initEdge() { memset(head, -1, sizeof(head)); cnt = 0; } int n, p[maxN]; void dfs(int now) { int to; for (int i = head[now]; i != -1; i = edge[i].next) { to = edge[i].to; if (p[to] == -1) { p[to] = p[now]^edge[i].val; dfs(to); } } } void input() { initEdge(); memset(p, -1, sizeof(p)); int u, v, w; for (int i = 1; i < n; ++i) { scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w); addEdge(v, u, w); } p[0] = 0; dfs(0); } void work() { int ans = 0; initTree(); for (int i = 0; i < n; ++i) { add(p[i]); ans = max(ans, p[i]^query(p[i])); } printf("%d\n", ans); } int main() { //freopen("test.in", "r", stdin); while (scanf("%d", &n) != EOF) { input(); work(); } return 0; }
ACM学习历程—POJ 3764 The xor-longest Path(xor && 字典树 && 贪心)
标签:
原文地址:http://www.cnblogs.com/andyqsmart/p/4957266.html