zoukankan      html  css  js  c++  java
  • Xor

    题目描述

    求一棵带边权的树的一条最大 Xor 路径的值。这里的“路径”不一定从根到叶子结点,中间一段路径只要满足条件也可以。

    输入格式

    第一行,一个整数 N ,表示一颗树有 N 个节点,接下来 N-1 行,每行三个整数 a,b,c 表示节点 a 和节点 b 之间有条权值为 c 的边。

    输出格式

    输出仅一行,即所求的最大值。

    样例数据 1

    输入  [复制]

    4
    1 2 3
    1 3 4
    1 4 7

    输出

    7

    备注

    【数据范围】

    对 40% 的输入数据 :数据退化为一条链;
    另对 10% 的输入数据 :N≤1000;
    对 100% 的输入数据 :1≤N≤100000, c≤231-1。

    题目分析

    套路Xor多半是trie树(普通/可持久化)。
    由于Xor的性质之 a ^ b ^ b = a, u与v之间路径的xor和就为sum[u] ^ sum[v](不必求lca)。
    于是可以将每个点到根节点的路径xor和计算出来,再将每个点的sum由高位到低位插入到trie树中。
    接下来扫描每个节点,对于当前节点的sum,从trie树根节点开始匹配,尽量向异或后为1的转移,取最大值即可。

    code

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 100005, L = 35;
    int n, ecnt, adj[N], go[N << 1], nxt[N << 1], len[N << 1], sum[N], ans = 0;
    
    inline int read(){
    	int i = 0, f = 1; char ch = getchar();
    	for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
    	if(ch == '-') f = -1, ch = getchar();
    	for(; ch >= '0' && ch <= '9'; ch = getchar())
    		i = (i << 3) + (i << 1) + (ch - '0');
    	return i * f;
    }
    
    inline void wr(int x){
    	if(x < 0) putchar('-'), x = -x;
    	if(x > 9) wr(x / 10);
    	putchar(x % 10 + '0');
    }
    
    struct node{
    	node *ch[2];
    	node(){}
    	inline void clean(){
    		ch[0] = ch[1] = NULL;
    	}
    }pool[N * L], *root = NULL, *tail = pool;
    
    inline void dfs(int u, int f){
    	for(int e = adj[u], v; e; e = nxt[e]){
    		if((v = go[e]) == f) continue;
    		sum[v] = sum[u] ^ len[e];
    		dfs(v, u);
    	}
    }
    
    inline int get(int s, int k){
    	return (s >>(k - 1)) & 1;
    }
    
    inline void insert(int s){
    	node *pos = root;
    	for(int i = 31; i >= 1; i--){
    		if(!pos->ch[get(s, i)])
    			(pos->ch[get(s, i)] = tail++)->clean();
    		pos = pos->ch[get(s, i)];
    	}
    }
    
    inline int getAns(int k){
    	int ret = sum[k];
    	node *pos = root;
    	for(int i = 31; i >= 1; i--){
    		if(pos->ch[get(sum[k], i) ^ 1]){
    			pos = pos->ch[get(sum[k], i) ^ 1];
    			ret |= (1 << (i - 1));
    		}
    		else{
    			pos = pos->ch[get(sum[k], i)];
    			ret ^= ((get(sum[k], i)) << (i - 1));
    		}
    	}
    	return ret;
    }
    
    inline void addEdge(int u, int v, int w){
    	nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v, len[ecnt] = w;
    }
    
    int main(){
    	//freopen("xor.in", "r", stdin);
    	ios::sync_with_stdio(false);
    	cin.tie(NULL), cout.tie(NULL);
    	n = read();
    	for(int i = 1; i < n; i++){
    		int x = read(), y = read(), z = read();
    		addEdge(x, y, z);
    		addEdge(y, x, z);
    	}
    	dfs(1, 0);
    	(root = tail++)->clean();
    	for(int i = 1; i <= n; i++) insert(sum[i]);
    	for(int i = 1; i <= n; i++) 
    		sum[i]=getAns(i),ans=max(ans,sum[i]);
    	wr(ans);
    	return 0;
    }
    
  • 相关阅读:
    如何计算二进制数的取值范围
    理解网络请求中的连接超时和读取超时
    两行代码玩转Spring Data排序和分页
    面试必问Elasticsearch倒排索引原理
    你知道Java的四种引用类型吗
    抛弃配置后的Spring终极教程
    Python学习第二篇
    Python
    关于always块内for循环的执行方式
    三态门实现“一读多写”总线结构
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7631922.html
Copyright © 2011-2022 走看看