牛客暑期训练第二场D-Kth Minimum (bfs+二进制压缩)

题目:https://ac.nowcoder.com/acm/contest/882/D

题意:求第k小权值团。团的意思是完全子图。

思路:用一个状态表示当前团中包含哪些节点,每次判断能加入哪些点,放入优先队列中依次取出。为了防止重复加入某些节点,保证每次加入的点都是比当前最大下标大的节点。判断一个节点是否能加入的条件是,此节点向量&当前团的状态是否等于当前团的状态值,若相等说明此节点与当前团中的每个节点都有一条边相连,可以加入。

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 105;

struct Node{
    LL w; int s;
    bitset<maxn>clique;
    bool operator < (const Node & a) const {return w > a.w;}
    Node(LL w, int s, bitset<maxn>clique):w(w), s(s), clique(clique){}
};
int x, n, k, w[maxn];
bitset<maxn>e[maxn];
LL bfs(){
    priority_queue<Node>que;
    bitset<maxn>raw; raw.reset();
    que.push(Node(0, 0, raw));
    while(que.size()){
        Node cur = que.top(); que.pop();
        if(--k == 0) return cur.w;
        for(int i=cur.s+1; i<=n; i++){
            if((e[i]&cur.clique) == cur.clique){
                bitset<maxn>b(cur.clique);
                b.set(i, 1);
                que.push(Node(cur.w+w[i], i, b));
            }
        }
    } 
    return -1;
}
int main(){
    cin >> n >> k;
    for(int i=1; i<=n; i++) cin >> w[i];
    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            scanf("%1d", &x), e[i][j] = x;
    cout << bfs() << endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值