POJ 3764 - The xor-longest Path - [DFS+字典樹變形]
題目連結:http://poj.org/problem?id=3764
Time Limit: 2000MS Memory Limit: 65536K
Description
In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:
$\oplus$ is the xor operator.
We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?
Input
The input contains several test cases. The first line of each test case contains an integer n(1<=n<=100000), The following n-1 lines each contains three integers u(0 <= u < n),v(0 <= v < n),w(0 <= w < 2^31), which means there is an edge between node u
Output
For each test case output the xor-length of the xor-longest path.Sample Input
4 0 1 3 1 2 4 1 3 6
Sample Output
7
Hint
The xor-longest path is 0->1->2, which has length $7 = 3 \oplus 4$
題意:
對一棵帶權樹,我們定義樹上的某條路徑 $p$ 的“異或長度”為該路徑上所有邊的邊權的異或值。要求你找出樹上“異或長度”最長的路徑,並求出其“異或長度”。
題解:
顯然對於樹上任意節點 $x$,我們可以用DFS遞推地求出 $dist[x] = dist[par[x]] \oplus w(par[x],x)$。
我們可以列舉所有路徑的兩個端點 $x,y$,其路徑為 $x \sim LCA(x,y) \sim y$。
那麼根據異或的性質,就有 $_{xor}length(x \sim y) = dist[x] \oplus dist[y]$,因為 $_{xor}length(root \sim LCA(x,y))$ 這一段同時出現在 $dist[x]$ 和 $dist[y]$ 中,異或之後即為 $0$,正好抵消掉了。
因此,問題就轉化為對於長度為 $n$ 的序列 $dist[1] \sim dist[n]$,尋找某一對 $(x,y)$ 使得 $dist[x] \oplus dist[y]$ 最大,給出最大值。該問題即CH 1602 - The XOR Largest Pair - [字典樹變形]。
AC程式碼:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=1e5+10; int n; struct Edge{ int u,v,w; int next; }; Edge E[2*maxn]; int head[maxn],ne; void init() { ne=0; memset(head,0,sizeof(head)); } void addedge(int u,int v,int w) { ++ne; E[ne].u=u, E[ne].v=v, E[ne].w=w; E[ne].next=head[u]; head[u]=ne; } int d[maxn]; bool vis[maxn]; void dfs(int u) { vis[u]=1; for(int i=head[u];i;i=E[i].next) { if(!vis[E[i].v]) { d[E[i].v]=d[u]^E[i].w; dfs(E[i].v); } } } namespace Trie { const int SIZE=maxn*32; int sz; struct TrieNode { int ed; int nxt[2]; }trie[SIZE]; void init() { sz=1; memset(trie,0,sizeof(trie)); } void insert(int x) { int p=1; for(int k=30;k>=0;k--) { int ch=(x>>k)&1; if(trie[p].nxt[ch]==0) trie[p].nxt[ch]=++sz; p=trie[p].nxt[ch]; } } int MaxXor(int x) { int res=0; int p=1; for(int k=30;k>=0;k--) { int ch=(x>>k)&1; if(trie[p].nxt[ch^1]) { p=trie[p].nxt[ch^1]; res|=1<<k; } else p=trie[p].nxt[ch]; } return res; } }; int main() { while(cin>>n) { init(); for(int i=1,u,v,w;i<n;i++) { scanf("%d%d%d",&u,&v,&w); addedge(u+1,v+1,w); addedge(v+1,u+1,w); } memset(vis,0,sizeof(vis)); memset(d,0,sizeof(d)); dfs(1); Trie::init(); int ans=0; for(int i=1;i<=n;i++) { Trie::insert(d[i]); ans=max(ans,Trie::MaxXor(d[i])); } cout<<ans<<endl; } }