Kth Minimum Clique
解题思路
我们可以从没有点开始,把点一个一个放进去,先把放入一个点的情况都存进按照权值排序的优先队列,每次在新出队的集合里增加一个新的点,为了避免重复,一个集合中的放入次序是按编号递增的,新放进去的点必须和已经在集合中的所有点之间都有一条边。当然我们不可能在入队时写两层循环来判断能不能放,所以用bitset,为1则说明集合里的点都和这个点之间有边,每次入队前利用&操作更新。
代码如下
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline int read(){
int res = 0, w = 0; char ch = 0;
while(!isdigit(ch)){
w |= ch == '-', ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -res : res;
}
const int N = 105;
ll v[N];
struct T{
ll w;
int x;
bitset<N> bt;
T(int x, ll w, bitset<N> bt): x(x), w(w), bt(bt){}
bool operator<(const T& a)const{
return w > a.w;
}
};
bitset<N> bt[N];
int main()
{
int n, k;
n = read(), k = read();
for(int i = 1; i <= n; i ++)
scanf("%lld%*c", &v[i]);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= n; j ++){
char ch = getchar();
bt[i][j] = ch - '0';
}
getchar();
}
if(k == 1){
cout << 0 << endl;
return 0;
}
-- k;
priority_queue<T> pq;
for(int i = 1; i <= n; i ++)
pq.push(T(i, v[i], bt[i]));
while(!pq.empty()){
T top = pq.top();
pq.pop();
-- k;
if(k == 0){
cout << top.w << endl;
return 0;
}
int x = top.x;
for(int i = x + 1; i <= n; i ++){
if(top.bt[i])
pq.push(T(i, top.w + v[i], top.bt & bt[i]));
}
}
cout << -1 << endl;
return 0;
}