Kth Minimum Clique
题意
给出n(n<100)个点的邻接表,和n个点的权值,求第k大的团(完全子图)
分析
n很小,并且好像没有什么算法和这个有关系,所以可以往暴力枚举的方向想,那么问题就变成了如果枚举?很容易发现一个问题,如何才能补充不漏地枚举呢?肯定要遵循一定的顺序,集合类问题一般是从已选的最后一个点的顺序往后枚举,这样就可以不重不漏了,那怎么实现第k大的,使用优先队列即可。邻接表使用bitmap存储方便操作,可以说是一道Bitmap入门题?
#include<bits/stdc++.h>
#define F first
#define S second
#define pb push_back
#define mkp make_pair
#define all(zzz) (zzz).being(),(zzz).end()
using namespace std;
typedef long long ll;
const int maxn=1e3+4;
char s[maxn][maxn];
ll a[maxn];
struct Node{
long long a;bitset<128> b;
Node(ll _a,bitset<128> _b){
a=_a;
b=_b;
}
bool operator<(const Node c)const{
return a>c.a;
}
};
bitset<128>judge[105];
int main(){
int n,k;
bitset<8>test;
// cout<<int(test[0])<<endl;
//cout<<z<<endl;
scanf("%d%d",&n,&k);
bitset<128>z;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=n;i++){
scanf("%s",s[i]+1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j)
if(s[i][j]=='1')
judge[i].set(j-1);
}
}
priority_queue<Node,vector<Node>>q;
for(int i=1;i<=n;i++){
z.reset();
q.push(Node(a[i],z.set(i-1)));
}
int cnt=1;
if(k==1){
cout<<0<<endl;
return 0;
}
while(!q.empty()){
z.reset();
auto tmp=q.top();
q.pop();
cnt++;
int id;
for(int i=127;i>=0;i--){
if((z.set(i)&tmp.b)[i]==1){
id=i+1;
break;
}
}
for(int i=id+1;i<=n;i++){
if((tmp.b&judge[i])==tmp.b){
auto tmp2=tmp;
q.push(Node(tmp.a+a[i],tmp2.b.set(i-1)));
}
}
if(cnt==k){
cout<<tmp.a<<endl;
return 0;
}
}
cout<<-1<<endl;
return 0;
}