BZOJ-1954 Pku3764 The xor-longest Path(trie)
阿新 • • 發佈:2020-11-23
題目描述
給定一棵 \(n(1\leq n\leq 10^5)\) 個節點的樹,樹上的每條邊都有一個權值。從樹中選擇兩個點 \(x\) 和 \(y\),把從 \(x\) 到 \(y\) 的路徑上的所有邊權 \(\text{xor}\)(異或)起來,求得到的最大結果。
分析
設 \(D[x]\) 表示根節點到 \(x\) 的路徑上所有邊權的 \(\text{xor}\) 值,顯然有:
\[D[x]=D[\text{father}(x)]\text{ xor }w\big(x,\text{father(x)}\big) \]根據上式,我們可以對樹進行一次深度優先遍歷,求出所有的 \(D[x]\)
所以,問題就變成了從 \(D[1]\) ~ \(D[N]\) 這 \(N\) 個數中選出兩個,\(\text{xor}\) 的結果最大,可以用 \(\text{trie}\) 樹來快速求解。
程式碼
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int trie[N*30][2],tot=1; int D[N],head[N],num_edge; struct Edge { int to; int dis; int Next; }edge[N<<1]; void add_edge(int from,int to,int dis) { edge[++num_edge].to=to; edge[num_edge].dis=dis; edge[num_edge].Next=head[from]; head[from]=num_edge; } void dfs(int x,int fa,int sum) { D[x]=sum; for(int i=head[x];i;i=edge[i].Next) { int y=edge[i].to,z=edge[i].dis; if(y!=fa) dfs(y,x,sum^z); } } void insert(int val) { int p=1; for(int i=30;i>=0;i--) { int num=(val>>i)&1; if(trie[p][num]==0) trie[p][num]=++tot; p=trie[p][num]; } } int search(int val) { int p=1; long long ans=0; for(int i=30;i;i--) { int num=(val>>i)&1; if(trie[p][!num]) { ans=ans+(1<<i); p=trie[p][!num]; } else p=trie[p][num]; } return ans; } int main() { int n; cin>>n; for(int i=1;i<=n-1;i++) { int u,v,w; scanf("%d %d %d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } dfs(1,0,0); for(int i=1;i<=n;i++) insert(D[i]); int ans=0; for(int i=1;i<=n;i++) ans=max(ans,search(D[i])); cout<<ans<<endl; return 0; }