2020牛客寒假算法基础集训营2 I建通道 位运算详解

题目链接:https://ac.nowcoder.com/acm/contest/3003/I
在这里插入图片描述
在这里插入图片描述
开始的时候想的是:把每两个点的花费都算一下,然后求最小生成树,但是感觉太复杂了,不会编出来,看了一下大神的代码后,才发现思路都是错的。

正确的思路是:
我们应该注意到题中的关键信息:在这里插入图片描述
首先应该确定,权值相同的两个点一定是连接的,因为费用为0,所以先排序去重一下。。。
我们知道1异或0后为1,所以如果存在那么一个数,只有他的那一位是1,设位a点,其他数的那一位全为0,那么此时可以把a点当成树的根,而其他点全部当成a的子节点,一共有n-1条边,易知所有边的费用都一样。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int maxn=2e5+5;
const int inf=0x3f3f3f;
ll q[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&q[i]);
    }
    sort(q+1,q+1+n);
    int tot=unique(q+1,q+1+n)-q-1;
    ll ans=0;
    for(int i=0;i<=30;i++)  ///枚举每一位
    {
        int num0=0;///0的个数
        int num1=0; ///1的个数
        for(int j=1;j<=tot;j++)
        {
            if(q[j]&(1ll<<i))
            {
                num1++;
            }
            else num0++;
        }
        if(num1&&num0)///如果该位上既存在1,又存在0,那么符合最优解
        {
            ans=(1ll<<i)*(tot-1);
            break;
        }
    }
    printf("%lld\n",ans);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值