1. 程式人生 > >【BZOJ】1954: Pku3764 The xor-longest Path

【BZOJ】1954: Pku3764 The xor-longest Path

return 分享 print 題解 first spl 數值 lose 復雜

【算法】trie樹+xor路徑

【題解】

套路1:統計從根到每個點的xor路徑和,由於xor的自反性,兩個點到根的xor路徑和異或起來就得到兩點間路徑和。

然後問題就是找到n個值中異或值最大的兩個值,考慮枚舉每個數字,對於一個數找到與其異或和最大的數。

套路2:對所有數值二進制建01-trie,對於一個已知數字在trie上每一層盡量往另一端走,O(log n)得到與其異或和最大的數。

復雜度O(n log n)。

另一種做法,用兩個指針從根往下,盡量分叉走,查詢總復雜度O(log n),但是建樹仍然需要O(n log n)。

技術分享
#include<cstdio>
#include<algorithm>
#include
<cstring> using namespace std; const int maxn=100010; struct edge{int v,w,from;}e[maxn*2]; int t[maxn*33][2],dfsnum=0,cnt=0,tot=0,p[maxn*2],first[maxn],n; bool val[maxn*33]; void insert(int u,int v,int w) {tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;} void push(int x){ int u=0;
for(int i=30;i>=0;i--){ bool c=x&(1<<i); if(!t[u][c])t[u][c]=++dfsnum; u=t[u][c]; } val[u]=1; } int find(int x){ int u=0,ans=0; for(int i=30;i>=0;i--){ bool c=x&(1<<i); if(!t[u][!c])u=t[u][c]; else{u=t[u][!c];ans|=(1
<<i);} } return ans; } void dfs(int x,int fa,int num){ push(p[++cnt]=num); for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){ dfs(e[i].v,x,num^e[i].w); } } int main(){ scanf("%d",&n); int u,v,w; for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&w); insert(u,v,w); insert(v,u,w); } dfs(1,-1,0); int ans=0; for(int i=1;i<=cnt;i++){ ans=max(ans,find(p[i])); } printf("%d",ans); return 0; }
View Code

【BZOJ】1954: Pku3764 The xor-longest Path