[BZOJ1954][Pku3764]The xor-longest Path

[BZOJ1954][Pku3764]The xor-longest Path

试题描述

 给定一棵n个点的带权树,求树上最长的异或和路径

输入

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
1 2 3
2 3 4
2 4 6

输出示例

7

数据规模及约定

见“输入

题解

这题中英文切换的。。。

一开始理解错题意了。。。把边权看成了点权,搞得还以为要点分治 + trie 树。。。

如果是边权,那么不难发现 xor(u, v)(即 u 到 v 的亦或和)= d[u] ^ d[v],d[u] 表示 u 到根节点的亦或和。

于是搞出 d 数组,把每个数插到 trie 中,然后对每个 d[i] 查询一遍 trie 树中与 d[i] 亦或的最大值,方法是贪心,从高位到底位尽量往与当前二进制位不同的方向走。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

#define maxn 100010
#define maxm 200010
#define maxnode 3200010

int n, m, head[maxn], nxt[maxm], to[maxm], dist[maxm], val[maxn];

void AddEdge(int a, int b, int c) {
	to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
	swap(a, b);
	to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
	return ;
}

int rt, ToT, ch[maxnode][2];
bool num[32];
void insert(int x) {
	int cnt = 0; memset(num, 0, sizeof(num));
	while(x) num[++cnt] = x & 1, x >>= 1;
	cnt = 31;
	int u = rt;
	for(int i = cnt; i; i--) {
		if(!ch[u][num[i]]) ch[u][num[i]] = ++ToT;
		u = ch[u][num[i]];
	}
	return ;
}
void build(int u, int fa, int v) {
	insert(v); val[u] = v;
	for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa)
		build(to[e], u, v ^ dist[e]);
	return ;
}
int query(int x) {
	int cnt = 0; memset(num, 0, sizeof(num));
	while(x) num[++cnt] = x & 1, x >>= 1;
	cnt = 31;
	int u = rt, ans = 0;
	for(int i = cnt; i; i--)
		if(ch[u][num[i]^1]) ans = ans << 1 | 1, u = ch[u][num[i]^1];
		else ans <<= 1, u = ch[u][num[i]];
	return ans;
}

int main() {
	n = read();
	for(int i = 1; i < n; i++) {
		int a = read(), b = read(), c = read();
		AddEdge(a, b, c);
	}
	
	ToT = rt = 1;
	build(1, 0, 0);
	int ans = 0;
	for(int i = 1; i <= n; i++) ans = max(ans, query(val[i]));
	
	printf("%d\n", ans);
	
	return 0;
}

 

posted @ 2017-03-01 16:44  xjr01  阅读(387)  评论(0编辑  收藏  举报