zoukankan      html  css  js  c++  java
  • P4551 最长异或路径(01trie模板)

    间隙

    大致题意

    给定一棵(n)个点的带权树,求最长的异或路径。

    异或路径指的是指两个结点之间唯一路径上的所有边权的异或

    (1≤n≤100000)

    分析

    01trie模板

    (f_i)表示从根节点到(i)节点的异或路径,有显然的递推公式:(f_v = f_{fa}⊕edge.w)

    根据异或的性质,(x)(y)之间的异或路径即为(f_v⊕f_u)((a⊕a = 0),即路径上重合的一部分恰好抵消)

    于是可以将每个(f_i)的二进制串从左到右插入到一颗(trie)树中,并在查询时尽可能地往与当前位相反的指针走即可

    (code)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 100010;
    struct e{
    	int u,v,w,next;
    }edge[MAXN<<1];
    int head[MAXN<<1],cnt = 0;
    void add(int u,int v,int w){
    	++cnt;
    	edge[cnt].w = w;
    	edge[cnt].u = u;
    	edge[cnt].v = v;
    	edge[cnt].next = head[u];
    	head[u] = cnt;
    }
    int n,ans = 0;
    int child[MAXN*40][2],tot = 1;
    int a[MAXN];
    void dfs(int u,int fa){
    	for(int i=head[u];i;i=edge[i].next){
    		int v = edge[i].v;
    		if(v==fa) continue;
    		a[v] = a[u]^edge[i].w;
    		dfs(v,u);
    	}
    }
    void insert(int a){
    	int p = 1;
    	for(int i=30;i>=0;i--){
    		int now = a>>i&1;
    		if(!child[p][now]) child[p][now] = ++tot;
    		p = child[p][now];
    	}
    }
    void findmax(int a){
    	int res = 0;
    	int p = 1;
    	for(int i=30;i>=0;i--){
    		int now = a>>i&1;
    		if(child[p][now^1]){
    			res|=1<<i;
    			p = child[p][now^1];
    		}
    		else{
    			p = child[p][now];
    		}
    	}
    	ans = max(ans,res);
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n-1;i++){
    		int u,v,w;
    		cin>>u>>v>>w;
    		add(u,v,w);
    		add(v,u,w);
    	}
    	dfs(1,0);
    	for(int i=1;i<=n;i++){
    		insert(a[i]);
    		findmax(a[i]);
    	}
    	cout<<ans;
    }
    
  • 相关阅读:
    Object类中常见的方法,为什么wait notify会放在Object里边
    什么是Java序列化和反序列化,如何实现Java序列化
    hashCode和equals方法的区别与联系
    MVC设计思想
    dstat命令--检查linux系统性能
    linux mint19.1解决网易云音乐安装后打不开的问题
    linux 修改用户密码
    MD5加密
    xmpp
    cocoapods安装
  • 原文地址:https://www.cnblogs.com/xcxc82/p/13907076.html
Copyright © 2011-2022 走看看