【POJ 3764】The xor-longest Path

【题目】

传送门

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:

x o r l e n g t h ( p ) = ⊕ e ∈ p w ( e ) _{xor}length(p)=\oplus_{e \in p}w(e) xorlength(p)=epw(e)
⊕ 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 n 个点的树,每条边有权值,任意找两个点 x x x y y y,把 x x x y y y 路径上的所有边权异或起来,求出最大的异或值

先任意找一个点作为作为根,定义 Xor[i] 为从根到 i i i 经过路径的异或值

那么, x x x y y y 路径上的边权异或值就是 Xor[x]^Xor[y](根据 x^x=0 可知重复的部分会被抵消掉)

那么这就相当于从 Xor[1] ~ Xor[n] 中选出两个数,使得异或值最大

那就是我之前写过的一道题了,戳这里


【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
int n,t,tot;
int v[N<<1],w[N<<1],nxt[N<<1];
int first[N],Xor[N],son[N<<5][2];
void init()
{
	t=tot=0;
	memset(son,0,sizeof(son));
	memset(first,0,sizeof(first));
}
void add(int x,int y,int k)
{
	t++;
	nxt[t]=first[x];
	first[x]=t;
	v[t]=y;
	w[t]=k;
}
void dfs(int x,int father)
{
	int i,k;
	for(i=first[x];i;i=nxt[i])
	{
		k=v[i];
		if(k!=father)
		{
			Xor[k]=w[i]^Xor[x];
			dfs(k,x);
		}
	}
}
int find(int x)
{
	int i,p=0,ans=0;
	for(i=31;~i;--i)
	{
		int k=!(x>>i&1);
		int now=(son[p][k])?k:k^1;
		p=son[p][now];
		if(now)  ans|=(1<<i);
	}
	return ans;
}
void insert(int x)
{
	int i,p=0;
	for(i=31;~i;--i)
	{
		int k=x>>i&1;
		if(!son[p][k])
		  son[p][k]=++tot;
		p=son[p][k];
	}
}
int main()
{
	int x,y,i,k;
	while(~scanf("%d",&n))
	{
		init();
		for(i=1;i<n;++i)
		{
			scanf("%d%d%d",&x,&y,&k);
			add(++x,++y,k),add(y,x,k);
		}
		dfs(1,0);
		int ans=0;
		for(i=1;i<=n;++i)
		{
			ans=max(ans,Xor[i]^find(Xor[i]));
			insert(Xor[i]);
		}
		printf("%d\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值