2019牛客暑期多校訓練營(第二場)-D Kth Minimum Clique

題目連接:https://ac.nowcoder.com/acm/contest/882/Dnode

題意:求給定點權無向圖中,點權和第k小的徹底子圖的點權和。(包括空集)this

思路:從空集開始,每找到一個徹底子圖,經過添加一個點來找到新的徹底子圖(只要該點與原來的全部點鄰接),並存入優先隊列中,每次取出權值和最小的來更新。用bitset來存儲當前徹底子圖中存了哪些點,爲了不更新重複的子圖,須要記錄每一個狀態上一次添加的是哪一個點,下次遍歷該點以後的點,從而防止重複。spa

AC代碼:code

#include<cstdio>
#include<algorithm>
#include<bitset>
#include<queue>
using namespace std;

typedef long long LL;
typedef bitset<105> BS;

struct node{
    LL sum;
    int pos;
    BS vis;
    node(){}
    node(LL s,int p,BS v){
        this->sum=s;
        this->pos=p;
        this->vis=v;
    }
    bool operator < (const node& other) const{
        return sum>other.sum;
    }
};

int n,k;
LL a[105];
BS b[105];
char s[105];

int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    for(int i=1;i<=n;++i){
        scanf("%s",s);
        for(int j=1;j<=n;++j)
            b[i][j]=s[j-1]-'0';
    }
    BS tmp;
    tmp.reset();
    priority_queue<node> pq;
    pq.push(node(0,1,tmp));
    while(!pq.empty()){
        node now=pq.top();pq.pop();
        if(--k==0){
            printf("%lld\n",now.sum);
            return 0;
        }
        for(int i=now.pos;i<=n;++i)
            if((b[i]&now.vis)==now.vis){
                now.vis[i]=1;
                pq.push(node(now.sum+a[i],i+1,now.vis));
                now.vis[i]=0;
            }
    }
    printf("-1\n");
    return 0;
}
相關文章
相關標籤/搜索