ACwing 144. 最长异或值路径 字典树

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

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

formula.png

⊕ 为异或符号。

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

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

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

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

1≤n≤100000
,
0≤u,v<n,
0≤w<231

输入样例:

4
0 1 3
1 2 4
1 3 6

输出样例:

7

样例解释

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

题意: 一棵树,有边权,求任意两点 U , V U,V U,V的路径上的亦或和最大


先推荐Y总的视频题解: https://www.acwing.com/video/81/



首先,假如选定一个根节点(例如0节点),
设根节点大到 U U U节点的异或和为 s u m u sum_u sumu
如下图, 5 5 5 9 9 9的路径异或和应该为 s u m 5 <mtext>   </mtext> x o r <mtext>   </mtext> s u m 9 sum_5~xor~sum_9 sum5 xor sum9
因为 s u m 2 sum_2 sum2会被 x o r xor两次 xor而消掉

dfs求出到每个点的路径异或和 s u m u sum_u sumu后,就变成了:
n n n s u m u sum_u sumu里挑出 A A A B B B,使得 A <mtext>   </mtext> x o r <mtext>   </mtext> B A~xor~B A xor B最大,
也就是AcWing 143. 最大异或对那题的题意

#define debug
#ifdef debug
#include <time.h>
#include "/home/majiao/mb.h"
#endif

#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>

#define MAXN ((int)1e5+7)
#define ll long long int
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)

using namespace std;

#define show(x...) \ do { \ cout << "\033[31;1m " << #x << " -> "; \ err(x); \ } while (0)

void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }

namespace FastIO{

	char print_f[105];
	void read() {}
	void print() { putchar('\n'); }

	template <typename T, typename... T2>
		inline void read(T &x, T2 &... oth) {
			x = 0;
			char ch = getchar();
			ll f = 1;
			while (!isdigit(ch)) {
				if (ch == '-') f *= -1; 
				ch = getchar();
			}
			while (isdigit(ch)) {
				x = x * 10 + ch - 48;
				ch = getchar();
			}
			x *= f;
			read(oth...);
		}
	template <typename T, typename... T2>
		inline void print(T x, T2... oth) {
			ll p3=-1;
			if(x<0) putchar('-'), x=-x;
			do{
				print_f[++p3] = x%10 + 48;
			} while(x/=10);
			while(p3>=0) putchar(print_f[p3--]);
			putchar(' ');
			print(oth...);
		}
} // namespace FastIO
using FastIO::print;
using FastIO::read;

int n, m, Q, K;
/** struct Node { Node* next[2]; Node() { memset(next, false, sizeof(next)); } } *root = new Node(); */
#define ch ( x >> i & 1 )
#define N 31
#if 0
void insert(int x) {
	Node* now = root;
	for(int i=N; i>=0; i--) {
		if(!now->next[ch]) now->next[ch] = new Node();
		now = now->next[ch];
	}
}

int search(int x) {
	Node* now = root;
	int ans = 0;
	for(int i=N; i>=0; i--) {
		if(now->next[!ch]) {
			ans += 1 << i;
			now = now->next[!ch];
		} else {
			now = now->next[ch];
		}
	}
	return ans;
}
#endif

struct Node {
	int v, w;
} ;

vector<Node> G[MAXN];

int a[MAXN], tot;
int tree[MAXN*32][2];
void insert(int x) {
	int now = 0;
	for(int i=N; i>=0; i--) {
		if(!tree[now][ch]) tree[now][ch] = ++tot;
		now = tree[now][ch];
	}
}

int search(int x) { //找打一个数,尽量使得二进制位前面的1最多
	int now = 0, ans = 0;
	for(int i=N; i>=0; i--) {
		if(tree[now][!ch]) { //因为不同才为1,所以每一步尽量走相反的位
			ans += 1 << i;
			now = tree[now][!ch];
		} else {
			now = tree[now][ch];
		}
	}
	return ans;
}

bool vis[MAXN];
void dfs(int u, int sum) {
	vis[u] = true;
	a[u] = sum;
	for(auto ed : G[u]) {
		int v = ed.v;
		if(vis[v]) continue ;
		dfs(v, sum^ed.w);
	}
}

int main() {
#ifdef debug
	freopen("test", "r", stdin);
	clock_t stime = clock();
#endif
	read(n);
	int u, v, w;
	for(int i=1; i<n; i++) {
		read(u, v, w);
		G[u].push_back({v, w}), G[v].push_back({u, w});
	}
	dfs(0, 0);
	for(int i=0; i<n; i++)
		insert(a[i]);
	int ans = 0;
	for(int i=0; i<n; i++)
		ans = max(ans, search(a[i]));
	printf("%d\n", ans);


#ifdef debug
	clock_t etime = clock();
	printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif 
	return 0;
}




全部评论

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务