そこに、N個のノードのツリー与えられる設定([I] [J wは\を ] \)は右端からの距離であり、右側のパスイソブチルまたは全ての側面上にあるI、J、の間のパスを定義しますそして、あなたは、任意の2点を選択した2点間の経路距離を最小化し、最大値を取得する\(1≤n≤100000\) 。
ソリューション
ツリーの問題、全く根の根はより良い研究、そこになっていない、通常設定その後、ルートノードへの各ノードのために維持される\(Sを[I] \)排他的なルートノードへの重み経路または点Iを表します。これは再びそれを維持することができ、DFS、私は余分をアピールしません。
このとき、任意の2点のためにi、jは距離の間となることを見出した\(W [I] \ウェッジW [J] \) 、排他的論理和結果の同じ数の同じ数が0であるため(\ W [i]は\ウェッジ[J] \)wは、正確ためこの種のルートノードに共通の祖先からI、Jを除去し、残りは自然距離Iのjからです。
そこで問題は、設定されてしまう(\ {[i]はワット\ \ \}) 2つの数値を選択し、かつ高いから文字列01として、限り、我々はトライ木を維持するように、これらの数字を明らかに、彼らの排他的論理和を最大化その後、低トライへの挿入、および非ゼロの数の数をすることができ、この1を作るために、トップダウンからトライ木から各番号を選択してみてください。
参照コード:
#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();
}