题目链接: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);
}