牛客竞赛第二场D Kth Minimum Clique 贪心+bitmap

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;
}
原文地址:https://www.cnblogs.com/ttttttttrx/p/11394571.html