最长异或值路径

给定一个树,树上的边都具有权值。

树中一条路径的异或长度被定义为路径上所有边的权值的异或和:

formula.png

⊕ 为异或符号。

给定上述的具有n个节点的树,你能找到异或长度最大的路径吗?

输入格式

第一行包含整数n,表示树的节点数目。

接下来n-1行,每行包括三个整数u,v,w,表示节点u和节点v之间有一条边权重为w。

输出格式

输出一个整数,表示异或长度最大的路径的最大异或和。

数据范围

1≤n≤100000
0≤u,v<n
0≤w<2^31输入样例:

4
0 1 3
1 2 4
1 3 6

输出样例:

7

样例解释

样例中最长异或值路径应为0->1->2,值为7 (3 ⊕ 4)

考虑,这样一个树结构,如果0是根,有0- > 1- > 2- >3,就是0到1的权值异或和异或1到3的异或和,再去掉多余部分,多余部分多了两次,而a ^ a = 0,0 ^ a = a,因此求每一个节点到根的异或和,求1到3的异或和让1到根和3到根的异或和异或一下即可

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int head[N * 2], nex[N * 2], cnt;
struct p{
	int to, dist;
	p(){}
	p(int to, int dist){this->to = to;this->dist = dist;}
};
p g[N * 2];
int aa[N];
void add(int a, int b, int c){
	g[++cnt].to = b;
	g[cnt].dist = c;
	nex[cnt] = head[a];
	head[a] = cnt;
}
void dfs(int ind, int father, int sum){
	aa[ind] = sum;
	for (int j = head[ind]; ~j; j = nex[j]){
		if(g[j].to != father){
			dfs(g[j].to, ind, sum ^ g[j].dist);
		}
	}
}
int trie[N * 32][2], tot = 1;
void insert(int Number){
	int p = 1;
	for (int i = 31; i >= 0; i--){
		int t = (Number >> i) & 1;
		if(!trie[p][t])trie[p][t] = ++tot;
		p = trie[p][t];
	}
}
int search(int Number){
	int p = 1;
	int res = 0;
	for (int i = 31; i >= 0; i--){
		int t = (Number >> i) & 1;
		if(t == 1){
			if(trie[p][0]){
				p = trie[p][0];
				res += (1 << i);
			}
			else p = trie[p][1];
		}
		else if(t == 0){
			if(trie[p][1]){
				p = trie[p][1];
				res += (1 << i);
			}
			else p = trie[p][0];
		}
	}
	return res;
}
int main()
{
	int n;
	scanf("%d", &n);
	memset(head, -1, sizeof head);
	memset(nex, -1, sizeof nex);
	for (int i = 1; i < n; i++){
		int a, b, c;
		scanf("%d %d %d", &a, &b, &c);
		add(a, b, c);
		add(b, a, c);
	}
	dfs(0, -1, 0);
	for (int i = 0; i < n; i++){
		insert(aa[i]);
	}
	int res = 0;
	for (int i = 0; i < n; i++){
		res = max(res, search(aa[i]));
	}
	printf("%d\n", res);
	return 0;
}

长时间不用邻接表,生疏了,,,,

posted @ 2019-10-10 22:07  correct  阅读(201)  评论(0)    收藏  举报