您的位置:首页 > 其它

poj 3764 The xor-longest Path (Trie树)

2017-07-25 21:01 399 查看

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:

(you ren kan ti ma? xian ran mei you. na wo jiu bu tie tu le.)

⊕ 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

题意

给出 1 棵树,询问树链上的最大连续异或和。

题解

利用异或和的性质可以得出求出dis(前缀异或和)后可以用神奇的性质求解答案(……)。这里用了指针和数组两种方法写的trie树。

代码1

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 400010;

int n, num, ans, tot, dis
, head
;

struct Trie {
int child[2];
void newnode() {
child[0] = 0, child[1] = 0;
}
} trie[N << 3];

struct Edge {
int v, next, w;
} edge[N << 3];

void add(int u, int v, int w) {
num ++;
edge[num].v = v;
edge[num].w = w;
edge[num].next = head[u];
head[u] = num;
}

void insert(int now) {
int root = 0, p;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 1;
else p = 0;
if(! trie[root].child[p]) {
trie[root].child[p] = ++ tot;
trie[tot].newnode();
}
root = trie[root].child[p];
}
}

void dfs(int u, int f, int w) {
dis[u] = w;
for(int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if(f == v) continue;
dfs(v, u, w^edge[i].w);
}
}

int query(int now) {
int p, ans = 0, root = 0;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 0;
else p = 1;
if(trie[root].child[p]) {
ans |= (1 << i);
root = trie[root].child[p];
}
else root = trie[root].child[! p];
}
return ans;
}

void clear() {
trie[0].newnode();
ans = -1, num = 0, tot = 0;
memset(dis, 0, sizeof(dis));
memset(trie, 0, sizeof(trie));
memset(head, 0, sizeof(head));
}

int main() {
while(scanf("%d", &n) != EOF){
clear();
for(register int i = 1; i < n; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(0, -1, 0);
for(register int i = 0; i < n; i ++) {
ans = max(ans, query(dis[i]));
insert(dis[i]);
}
printf("%d\n", ans);
}
return 0;
}


代码2

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1000010;

int n, num, ans = 0, dis
, head[N << 3];

struct Trie {
Trie *child[2];
} pool[N << 3], *tail = pool, *root;

struct Edge {
int v, next, w;
} edge[N << 3];

Trie *newtrie() {
Trie *node = ++ tail;
node -> child[0] = NULL, node -> child[1] = NULL;
return node;
}

void add(int u, int v, int w) {
num ++;
edge[num].v = v;
edge[num].w = w;
edge[num].next = head[u];
head[u] = num;
}

void insert(int now) {
Trie *node = root;
int p;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 1;
else p = 0;
if(node -> child[p] == NULL)
node -> child[p] = newtrie();
node = node -> child[p];
}
}

void dfs(int u, int f, int w) {
dis[u] = w;
for(int i = head[u]; i; i = edge[i].next) {
int v = edge[i].v;
if(f == v) continue;
dfs(v, u, w^edge[i].w);
}
}

int query(int now) {
Trie *node = root;
int ans = 0, p;
for(int i = 30; i >= 0; i --) {
if(now & (1 << i)) p = 0;
else p = 1;
if(node -> child[p] != NULL) {
ans |= (1 << i);
node = node -> child[p];
}
else if(node -> child[p ^ 1] != NULL)
node = node -> child[p ^ 1];
else return 0;
}
return ans;
}

void clear() {
delete tail;
delete root;
ans = 0, num = 0;
memset(dis, 0, sizeof(dis));
memset(head, 0, sizeof(head));
}

int main() {
while(scanf("%d", &n) != EOF){
clear();
root = newtrie();
for(register int i = 1; i < n; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
}
dfs(0, -1, 0);
for(register int i = 0; i < n; i ++) {
ans = max(ans, query(dis[i]));
insert(dis[i]);
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: