第k小团+bitset优化——牛客多校第2场D

时间:2023-03-09 15:30:00
第k小团+bitset优化——牛客多校第2场D

模拟bfs,以空团为起点,用堆维护当前最小的团,然后进行加点更新

在加入新点时要注意判重,并且用bitset来加速判断和转移构造

#include<bits/stdc++.h>
#include<bitset>
#include<queue>
using namespace std;
#define ll long long
char mp[][];
int n,k;
ll a[];
bitset<>bit[];
struct Node{
ll w;
bitset<>b;//团内点的状态
Node(){w=;b.reset();}
Node(ll w,bitset<>b):w(w),b(b){}
};
bool operator<(Node a,Node b){
return a.w>b.w;
}
priority_queue<Node> pq;//团按权值升序排列 int main(){
cin>>n>>k;
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
for(int i=;i<=n;i++)scanf("%s",mp[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
if(mp[i][j]=='')bit[i][j]=;
else bit[i][j]=;
}
pq.push(Node());
int cnt=;ll ans=;
while(pq.size()){
Node cur=pq.top();pq.pop();
//for(int i=1;i<=n;i++)cout<<cur.b[i];
//puts(""); cnt++;
if(cnt==k){
ans=cur.w;
break;
}
//要保证所有在pq里出现过的团都是唯一的,即不能重复加入状态相同的团,
//更新时只加比当前团最大的点编号大的点
int start=;
for(int i=n;i>=;i--)if(cur.b[i]){
start=i+;break;
} for(int i=start;i<=n;i++)if(!cur.b[i]){//第i个点没在团里
//for(int j=1;j<=n;j++)cout<<bit[i][j];
//puts("");
if((cur.b&bit[i])==cur.b){
Node tmp=cur;
tmp.w+=a[i];
tmp.b[i]=;
pq.push(tmp);
}
}
} if(cnt==k)cout<<ans<<endl;
else cout<<-<<endl;
}