The xor-longest Path

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.

样例输入

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)

#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=3

int 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;
	// 新的边的终点为v
	weight[now] = w;
	// 新的边的权值为w
	head[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);
		else
			return 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;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值