给定一个树,树上的边都具有权值。
树中一条路径的异或长度被定义为路径上所有边的权值的异或和:
⊕ 为异或符号。
给定上述的具有n个节点的树,你能找到异或长度最大的路径吗?
输入格式
第一行包含整数n,表示树的节点数目。
接下来n-1行,每行包括三个整数u,v,w,表示节点u和节点v之间有一条边权重为w。
输出格式
输出一个整数,表示异或长度最大的路径的最大异或和。
数据范围
1≤n≤100000
0≤u,v
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
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;
}
长时间不用邻接表,生疏了,,,,