专栏文章
题解:CF2026E Best Subsequence
CF2026E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqder21
- 此快照首次捕获于
- 2025/12/04 02:58 3 个月前
- 此快照最后确认于
- 2025/12/04 02:58 3 个月前
前言
什么最小割、最大权闭合子图之类的,我不知道啊。就是二分图的最大独立集呀。
思路
先考虑每一个数。
数与数之间互不干扰,数位与数位之间也互不影响。只有数与数位会互相影响。二分图?
数与数之间互不干扰,数位与数位之间也互不影响。只有数与数位会互相影响。二分图?
建一张二分图,左侧为 个数,右侧为 个二进制位。考虑连边。如果一个数 二进制下的第 位数为 ,会产生负贡献,那就连边。
显然,这是一个最大独立集问题,跑一遍匹配即可。因为每一个点仅会与另外一个点匹配。根据按位或的性质,如果两个数相同二进制位上的数都是 ,它还是 ,和二分图匹配的特点正好相同。因此没有问题。
代码
CPP#include<iostream>
#include<cstring>
using namespace std;
int t,n;
const int N=1e5+10;
long long a[N];
int h[N],e[N],ne[N],idx;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int match[N];
bool st[110];
bool find(int x){
for(int i=h[x];i!=-1;i=ne[i]){
int j=e[i];
if(!st[j]){
st[j]=true;
if(match[j]==0||find(match[j])){
match[j]=x;
return true;
}
}
}
return false;
}
int main(){
cin>>t;
while(t--){
scanf("%d",&n);
idx=0;
for(int i=1;i<=100;i++){
h[i]=-1,match[i]=0;
}
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
for(int j=0;j<=60;j++){
if(a[i]>>j&1){
add(i,j+1);
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
memset(st,0,sizeof st);
ans+=find(i);
}
cout<<n-ans<<endl;
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...