思路
最终形成的最小总权值的图一定是一颗树,再仔细思考一下,树上任意两点的权值是原树上从根异或到这两点的值。所以先对于每个点求一个(w[i]),即从根异或到这一点的值,然后依照(w[i])搞一个最小异或生成树就是答案了。
至于如何求最小异或生成树,首先一定要把所有(w[i])加入trie里,trie中每个分叉就代表要从左右两个分叉中选异或值尽量小的一对点。这里可以使用dsu on tree,或者直接暴力dfs。对于这种(N=10^5)的数据,也可以直接套最小生成树板子,当然不是prim或者kruskal,而是用一个平常接触不多的算法:Borůvka's algorithm
代码
直接暴力dfs了(〃'▽'〃)。
#include <bits/stdc++.h>
#define x first
#define y second
#define pushb push_back
#define pushf push_front
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
const double PI=acos(-1.0);
const double eps=1e-8;
const int inf=0x3f3f3f3f;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
inline LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
inline LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
inline LL qpow(LL x,LL k=mod-2,LL _mod=mod){LL res=1;while(k){if(k&1) res=res*x%_mod;k>>=1;x=x*x%_mod;}return res;}
const int N=1e5+10;
int n,head[N],to[N*2],nxt[N*2],val[N*2],tot,fx[N],cnt;
void add(int u,int v,int w){
to[++tot]=v;nxt[tot]=head[u];val[tot]=w;head[u]=tot;
}
struct Trie{
int ch[N*31][2],tot;
void insert(int x){
int p=0;
for(int i=30;i>=0;i--){
int c=(x>>i)&1;
if(!ch[p][c]) ch[p][c]=++tot;
p=ch[p][c];
}
}
LL dfs1(int u,int power){
if(power<0) return 0;
LL res=0;
if(ch[u][0]&&ch[u][1]) res+=dfs2(ch[u][0],ch[u][1],power-1)+(1ll<<power);
if(ch[u][0]) res+=dfs1(ch[u][0],power-1);
if(ch[u][1]) res+=dfs1(ch[u][1],power-1);
return res;
}
LL dfs2(int u1,int u2,int power){
if(power<0) return 0;
LL res=inf;
if(ch[u1][0]&&ch[u2][0]) res=min(res,dfs2(ch[u1][0],ch[u2][0],power-1));
if(ch[u1][1]&&ch[u2][1]) res=min(res,dfs2(ch[u1][1],ch[u2][1],power-1));
if(ch[u1][0]&&ch[u2][0]||ch[u1][1]&&ch[u2][1]) return res;
if(ch[u1][0]&&ch[u2][1]) return dfs2(ch[u1][0],ch[u2][1],power-1)+(1ll<<power);
else return dfs2(ch[u1][1],ch[u2][0],power-1)+(1ll<<power);
}
}tr;
void predfs(int u,int fa){
for(int i=head[u];i;i=nxt[i]){
if(to[i]==fa) continue;
fx[to[i]]=fx[u]^val[i];
predfs(to[i],u);
}
}
int main(){
scanf("%d",&n);
for(int i=1,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
u++,v++;
add(u,v,w);add(v,u,w);
}
predfs(1,0);
for(int i=1;i<=n;i++) tr.insert(fx[i]);
printf("%lld
",tr.dfs1(0,30));
return 0;
}