zoukankan      html  css  js  c++  java
  • 最长异或值路径

    最长异或值路径

    给出一棵有n个节点的树,设(w[i][j])为i,j之间的边权,定义一条路径的距离,为这条路径上所有边权的异或和,请你选出任意两个点,最小化这两点之间的路径距离,并求出这个最大值,(1≤n≤100000)

    树的问题,无根变有根,更加好研究,通常维护出每个节点到根节点的信息,于是设(s[i])表示点i到根节点的路径的权值的异或和,这个一遍dfs就可以维护出来,我不再赘诉了。

    此时发现对于任意两个点i,j之间的距离就变成(w[i]wedge w[j]),原因在于相同的数异或相同的数结果为0,而(w[i]wedge w[j]),恰好因为这个性质,除去了i,j最近公共祖先到根节点的距离,剩下的距离自然都是i,j的距离了。

    于是现在问题变成从集合({w[i]})选出两个数,最大化它们的异或和,显然我们只要维护一棵trie树,将这些数当做01串从高位到低位插入trie树,然后对于每个数从trie树从上往下尽量选择让该数的这一位不为0的数字即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define Size 100050
    using namespace std;
    struct point{
    	point *next;int to,w;
    }*pt,*head[Size];
    bool is[Size];
    int dis[Size],trie[Size*31][2],tot;
    void dfs(int);
    il int ask(int);
    il void read(int&),
    	link(int,int,int),
    	insert(int);
    template<class free>
    il free Max(free,free);
    int main(){
    	int n,ans(0);read(n);
    	for(int i(1),u,v,w;i<n;++i)
    		read(u),read(v),read(w),
    			link(u,v,w),link(v,u,w);dfs(0);
    	for(int i(1);i<=n;++i)
    		ans=Max(ans,ask(dis[i]));
    	printf("%d",ans);
    	return 0;
    }
    template<class free>
    il free Max(free a,free b){
    	return a>b?a:b;
    }
    il int ask(int x){
    	int ans(0),p(0);
    	for(int i(30);i>=0;--i)
    		if(trie[p][x>>i&1^1])
    			p=trie[p][x>>i&1^1],
    				ans|=1<<i;
    		else p=trie[p][x>>i&1];
    	return ans;
    }
    il void insert(int x){int p(0);
    	for(int i(30);i>=0;--i){
    		if(!trie[p][x>>i&1])
    			trie[p][x>>i&1]=++tot;
    		p=trie[p][x>>i&1];
    	}
    }
    void dfs(int x){is[x]|=true,insert(dis[x]);
    	for(point *i(head[x]);i!=NULL;i=i->next){
    		if(is[i->to])continue;
    		dis[i->to]=dis[x]^i->w,dfs(i->to);
    	}
    }
    il void link(int u,int v,int w){
    	pt=new point{head[u],v,w},head[u]=pt;
    }
    il void read(int &x){
    	x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
    	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    
  • 相关阅读:
    Android文字上下滚动
    Java怎么去除字符串中的多个空白【split(" ")与split("\s+")】
    Java:Scanner.nextLine()和Scnner.next()的区别,以及多条nextLine()输入问题的解决方法
    SQL server报错18456(又名SQL server怎么用sa登入)
    Android Studio快速自动生成findViewById
    java.sql.Date和java.util.Date的联系与区别【转载】
    Linux Crontab 不执行
    PostgreSQL 全量 增量 归档 备份工具 pg_rman介绍与使用(转载)
    Rman备份的保留策略(retention policy) (转载)
    Oracle RMAN block_change_tracking(块更改追踪)
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11248071.html
Copyright © 2011-2022 走看看