题意: 有一个图,每个节点都有自己的权值,找一个子图,所有节点相加的权值是第k小,(权值为0的图为第一小,也就是空图),且子图的条件是,任意两个点都相邻。
题解:当k==1时,答案是0,当k大于1时,我们先把所有节点加入优先队列中,然后优先队列以权值小的优先,当top出来一个值,再从这个节点能衍生的点加入都优先队列里面。
难点就是,如何判断加入是否与该点相邻,这里要用个很厉害的东西叫bitset,可以百度查下,然后就直接二进制操作了。
#include<bits/stdc++.h>
using namespace std;
const int N = 107;
bitset<N> mp[N];
int n,k,value[N];
struct node{
long long v;
int pos;
bitset<N> a;
node(){}
node(long long v,int pos,bitset<N> a){
this->v = v;
this->pos = pos;
this->a = a;
}
bool operator<(const node &x)const{
return v > x.v;
}
};
void work(){
priority_queue<node> q;
for (int i = 1; i <= n;i++){
q.push(node(1ll*value[i], i, mp[i]));
}
if(k==1){
printf("0\n");
return;
}
while(!q.empty()){
node cd = q.top();
q.pop();
k--;
if(k==1){
printf("%lld\n", cd.v);
return;
}
for (int i = cd.pos + 1; i <= n;i++){
if(cd.a[i]){
q.push(node(1ll * (cd.v + 1ll * value[i]), i, mp[i] & cd.a));
}
}
}
printf("-1\n");
}
int main(){
int x;
scanf("%d%d", &n,&k);
for (int i = 1; i <= n;i++){
scanf("%d" ,& value[i]);
}
for (int i = 1; i <= n; i++){
for (int j = 1; j <= n; j++){
scanf("%1d", &x);
mp[i][j] = x;
}
}
work();
}