题面:
大意:给定一棵 n 个点的带权树,结点下标从 1 开始到 N 。寻找树中找两个结点,求最长的异或路径。
因为 a xor a = 0
所以只需要dfs求一遍所有点到根节点的异或和。
然后改为01串放入trie树中。
因为是异或操作,所以当这个节点为0时,要找节点为1的儿子,会让异或更大。
所以贪心求解。
代码如下。
#include#include #define rr register#define sc(x) scanf("%d",&x) using namespace std;const int maxn=100001;int n;int head[maxn],tot;struct node{ int nxt,to,val; #define to(x) e[x].to #define val(x) e[x].val #define nxt(x) e[x].nxt}e[maxn<<1];inline void add(int u,int v,int w){ to(++tot)=v,val(tot)=w; nxt(tot)=head[u]; head[u]=tot; }int xorr[maxn];//所有点到根节点的异或值inline void dfs(int now,int ls){ for(rr int i=head[now];i;i=nxt(i)){ if(to(i)!=ls){ xorr[to(i)]=xorr[now]^val(i); dfs(to(i),now); } }}int cnt,trie[maxn*31][2];inline void build(int x,int p){ for(rr int i=1<<30;i;i>>=1){ bool c=x&i; if(!trie[p][c]) trie[p][c]=++cnt; p=trie[p][c]; }}inline int ask(int x,int p){ int ans=0; for(rr int i=1<<30;i;i>>=1){ bool c=x&i; if(trie[p][c^1]) ans+=i,p=trie[p][c^1]; else p=trie[p][c]; } return ans;}int main(){ sc(n); for(rr int i=1;i