Codeforces Contest 888 G Xor-MST —— 求异或最小生成树

This way

题意:

给你一张完全图,每个点都有一个值,每条边的值是连接两个点的异或,问你这张图里面的最小生成树的权值和是多少。

题解:

异或最小我们用tire树来找的话一定是使得这两个数尽量在同一个子树上,那么我们就可以这样做:直接将所有的数放入一个字典树里面,那么相同的数相连一定是0,所以相同的数只保留一个即可,接下来一个子树一个子树做,两个不相交的集合一定是左子树上找一个值与右子树上找一个值异或最小,那么我们只需要枚举较小的子树的值,在较大的子树上找最小异或即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+5;
int tr[N*32][2],p[N*32],cnt=1,a[N];
vector<int>vec[N];
void add(int s,int id)
{
    int now=1;
    for(int i=30;i>=0;i--)
    {
        int &ne=tr[now][((s>>i)&1)];
        if(!ne)
            ne=++cnt;
        now=ne;
    }
    p[now]=id,vec[id].push_back(a[id]);
}
int finds(int root,int s,int dep)
{
    int now=root;
    int ans=0;
    for(int i=dep-1;i>=0;i--)
    {
        int ne=tr[now][((s>>i)&1)];
        if(!ne)
            ans|=(1<<i),ne=tr[now][(1^((s>>i)&1))];
        now=ne;
    }
    return ans|(1<<dep);
}
ll ans;
void dfs(int x,int dep)
{
    if(!x||!dep)
        return ;
    int ls=tr[x][0],rs=tr[x][1];
    dfs(ls,dep-1),dfs(rs,dep-1);
    if(!ls||!rs)
    {
        p[x]=p[ls+rs];
        return ;
    }
    int lid=p[ls],rid=p[rs];
    if(vec[rid].size()>vec[lid].size())
        swap(ls,rs),swap(lid,rid);
    int mi=2e9;
    for(int i=0;i<vec[rid].size();i++)
    {
        mi=min(mi,finds(ls,vec[rid][i],dep-1));
        vec[lid].push_back(vec[rid][i]);
    }
    vec[rid].clear();
    p[x]=p[ls];
    ans+=(ll)mi;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++)
        if(a[i]!=a[i-1])
            add(a[i],i);
    dfs(1,31);
    printf("%lld\n",ans);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值