zoukankan      html  css  js  c++  java
  • 最长异或值路径【字典树应用】

    任何新类型的题,都可以转换成自己熟悉的题来解答。

    就像下面的这题:


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

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

    formula.png

    ⊕ 为异或符号。

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

    输入格式

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

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

    输出格式

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

    数据范围

    1≤n≤100000<?XML:NAMESPACE PREFIX = "[default] http://www.w3.org/1998/Math/MathML" NS = "http://www.w3.org/1998/Math/MathML" />1≤n≤100000,
    0≤u,v<n0≤u,v<n,
    0≤w<2310≤w<231

    输入样例:
    4
    0 1 3
    1 2 4
    1 3 6
    
    输出样例:
    7
    
    样例解释

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


    此题思路:

    首先,这里时求树中的任意两节点间的异或长度最大值,但是我们可以求出根节点到各个节点的异或和,这里假设D[x]表示根到x的边权所有的异或值则有

    D[x] = D[father[x]] xor weight(x,fahter[x])

    这里的weight(x, father[x])表示的x到它父亲边的权值。

    因此,我们转换思路先求出每个节点到根的异或值,然后用D[i]保存。问题就变成了,给出一段数据,求最大异或和。

    这里提示一下:

    D[x] xor D[y]就是这条路径的异或长度,因为其中重复的路径已经通过异或的性质减去。

    所以通过字典树求出答案,和上一题的,最大异或和https://www.acwing.com/problem/content/145/

    差不多。

    代码:


      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstring>
      4 using namespace std;
      5 
      6 const int N = 1e5 + 5, M = 3e6;
      7 int h[N], e[N*2], c[N*2], ne[N*2], cnt, n;
      8 int trie[M][2], tot;
      9 int d[N];
     10 void add(int u, int v, int w){
     11 	e[cnt] = v, c[cnt] = w, ne[cnt] = h[u], h[u] = cnt ++;//邻接表存储树 
     12 }
     13 
     14 void dfs(int u, int father, int sum){
     15 	d[u] = sum;
     16 	for(int i = h[u]; ~i; i = ne[i]){
     17 		int j = e[i];
     18 		if(j != father)
     19 			dfs(j, u, sum^c[i]);
     20 	}
     21 }
     22 
     23 void insert(int x) {
     24 	int p = 0;
     25 	for(int i = 30; ~i; -- i) {
     26 		int &s = trie[p][x >> i & 1];
     27 		if(!s) s = ++tot;
     28 		p = s;
     29 	}
     30 }
     31 
     32 int query(int x) {
     33 	int p = 0, res = 0;
     34 	for(int i = 30; i >= 0; -- i){
     35 		int s = x >> i & 1;
     36 		if(trie[p][!s]){
     37 			p = trie[p][!s];
     38 			res += 1 << i;
     39 		}
     40 		else p = trie[p][s];
     41 	}
     42 	return res;
     43 }
     44 
     45 int main() {
     46 	cin >> n;
     47 	memset(h, -1, sizeof(h));
     48 	for(int i = 0; i < n-1; ++ i) {
     49 		int u, v, w;
     50 		cin >> u >> v >> w;
     51 		add(u, v, w);
     52 		add(v, u, w);
     53 	}
     54 	dfs(0, -1, 0);
     55 	for(int i = 0; i < n; ++ i)
     56 		insert(d[i]);
     57 
     58 	int res = 0;
     59 	for(int i = 0; i < n; ++ i)
     60 		res = max(res, query(d[i]));
     61 	cout << res << endl;
     62 	return 0;
     63 }
     64 
     65 


  • 相关阅读:
    CVE-2017-10271
    [GKCTF2020]cve版签到
    [GXYCTF2019]禁止套娃 无参数RCE
    [护网杯 2018]easy_tornado
    记两道xctf上的web进阶区 反序列化
    msf卸载win defender
    Cron表达式详解
    Linux ifconfig只有lo没有别的网络的问题
    记一道文件上传
    【解决】手机安卓已经导入burp证书,但仍提示此证书并非来自被信任的机构
  • 原文地址:https://www.cnblogs.com/rstz/p/13374722.html
Copyright © 2011-2022 走看看