题目: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;
}