【POJ 3764】The xor-longest Path

1.题目链接。题意:给一颗树,带有边权,求一下树上路径异或和最大值。

2.其实和之前BZOJ那道题有着异曲同工之妙,只需要的dfs一下,在dfs的过程中记一下当前节点到根节点的路径上的异或值,然后把这个值插到01字典树上,完事之后每次在字典树上查询最值即可,有人可能会觉得,有的点会重复计算,这样会导致出现的不是一条路径,而是两条或者多条路径交叉,其实这种情况时不存在的,因为只要一个数被计算两次,那么对整体答案将没有贡献,这样这条路径就在这个点断开成两条,所以不会出现交叉。

#include<stdio.h>
#include<string.h>
#include<iostream>
#define MAXN 400010
using namespace std;
struct Trie
{
	int tol;
	int val[MAXN * 32];
	int ch[MAXN * 32][2];
	void init()
	{ //初始化 
		tol = 1;
		ch[0][0] = ch[0][1] = 0;
	}
	void insert(int x)
	{
		int u = 0;
		for (int i = 32; i >= 0; i--)
		{
			int v = (x >> i) & 1;
			if (!ch[u][v])
			{
				ch[tol][0] = ch[tol][1] = 0;
				val[tol] = 0;
				ch[u][v] = tol++;
			}
			u = ch[u][v];
		}
		val[u] = x;
	}
	int query(int x)
	{
		int u = 0;
		for (int i = 32; i >= 0; i--)
		{
			int v = (x >> i) & 1;
			if (ch[u][v ^ 1]) u = ch[u][v ^ 1];
			else u = ch[u][v];
		}
		return x ^ val[u];
	}
}tr;


struct node
{
	int val, next, to;
}mp[MAXN*2];
int cnt, head[MAXN];
int ans;
void init()
{
	ans = 0;
	int cnt = 0;
	memset(head, -1, sizeof(head));
}
void add(int u, int v, int w)
{ 
	mp[cnt].to = v;
	mp[cnt].val = w;
	mp[cnt].next = head[u];
	head[u] = cnt++;
}
void dfs(int u, int pre, int val)
{
	//首先把这个值插入到字典树上去
	tr.insert(val);
	for (int i = head[u]; ~i; i = mp[i].next)
	{
		int v = mp[i].to;
		if (v == pre)continue;
		ans = max(ans, tr.query(val ^ mp[i].val));
		dfs(v, u, val ^ mp[i].val);
	}
}



int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		init();
		tr.init();
		for (int i = 1; i < n; i++)
		{
			int u, v, w;
			scanf("%d%d%d", &u, &v, &w);
			add(u, v, w);
			add(v, u, w);
		}
		dfs(0, -1, 0);
		printf("%d\n", ans);
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值