题目链接:http://poj.org/problem?id=3764
The xor-longest Path
Time Limit: 2000MS | Memory Limit: 65536K |
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:
⊕ 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
Hint
The xor-longest path is 0->1->2, which has length 7 (=3 ⊕ 4)
题意:
给你一棵n个节点n-1条边的树,每个边都有一个边权,从中选出任意两个节点使这两个节点间的所有边权的异或值最大。
思路:
设D[x]为根节点到x的路径上的所有边权的异或值,显然D[x]=D[father[x]] xor weight(x,father[x])。根据上式先进行一次深度优先搜索,求出所有的D[x]。设有两节点x和y,根据异或性质 a xor a=0,x到根与y到根的路径上的所有重叠部分恰好抵消,所以x到y的路径上的所有边权的异或值等于D[x] xor D[y].
所以问题转变为从D[0]--D[N-1]这N个数中选出两个使其异或和最大,用0-1字典树解决即可。
注意
(1)存图时用链式前向星,因为多组输入,每次初始化清空数组时,用邻接表可能会超时。链式前向星具体见:https://blog.csdn.net/qq_30331643/article/details/68621435.
(2)字典树见:https://blog.csdn.net/fire_to_cheat_/article/details/79616679
代码:
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
const int maxn=1e5+5;
struct edge{
int to,w,next;
}e[maxn*2];
int head[maxn],cnt=0;
int trie[maxn*32][2],a[maxn],n,MAX=0,tot=0;
void init()
{
memset(trie,0,sizeof trie);
memset(a,0,sizeof a);
memset(e,0,sizeof e);
memset(head,-1,sizeof head);
MAX=0;
tot=0;
cnt=0;
}
void insert(int x)
{
int rt=0;
for(int i=30;i>=0;i--)
{
int t=(x>>i)&1;
if(!trie[rt][t])
trie[rt][t]=++tot;
rt=trie[rt][t];
}
return;
}
int query(int x)
{
int res=0,rt=0;
for(int i=30;i>=0;i--)
{
int t=(x>>i)&1;
if(trie[rt][t^1])
{
res|=(1<<i);
t=t^1;
}
rt=trie[rt][t];
}
return res;
}
void dfs(int v,int f,int s)
{
a[v]=s;
for(int i=head[v];~i;i=e[i].next)
{
if(e[i].to!=f)
{
dfs(e[i].to,v,s^e[i].w);
}
}
}
void addedge(int v,int u,int w)
{
e[cnt].to=u;
e[cnt].w=w;
e[cnt].next=head[v];
head[v]=cnt++;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
init();
for(int i=0;i<n-1;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
dfs(0,0,0);
for(int i=0;i<n;i++)
{
MAX=max(MAX,query(a[i]));
insert(a[i]);
}
cout<<MAX<<endl;
}
return 0;
}