2019牛客暑期多校训练营(第二场)D Kth Minimum Clique(bitset+暴力枚举)

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

题目大意:给出一个无向图,让你求第k小的完全子图

解题报告:

  考虑什么情况下,i点可插入。

由于完全子图的性质,当前状态应当真包含和 i 相连的边,对于i的判断可以用bitset,轻松完成状态的转移。但是这样算出来会有重复的情况,所以考虑枚举顺序的问题,每次从最后一个1开始往后找情况然后转移,这样搜出来的状态就不会有重复的。

  bitset不懂戳这里!

AC代码:

 1 #include<bits/stdc++.h>
 2 
 3 #define numm ch-48
 4 #define pd putchar(' ')
 5 #define pn putchar('
')
 6 #define pb push_back
 7 #define fi first
 8 #define se second
 9 #define fre1 freopen("1.txt","r",stdin)
10 #define fre2 freopen("2.txt","w",stdout)
11 using namespace std;
12 template <typename T>
13 void read(T &res) {
14     bool flag=false;char ch;
15     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
16     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
17     flag&&(res=-res);
18 }
19 template <typename T>
20 void write(T x) {
21     if(x<0) putchar('-'),x=-x;
22     if(x>9) write(x/10);
23     putchar(x%10+'0');
24 }
25 typedef long long ll;
26 const int maxn=1e2+7;
27 const int N=60;
28 const ll mod=1e9+7;
29 struct node {
30     ll w;
31     bitset<maxn>bs;
32 };
33 struct cmp {
34     bool operator()(node a,node b) {
35         return a.w>b.w;    ///小顶堆
36     }
37 };
38 ll w[maxn];
39 int n,k;
40 bitset<maxn>edge[maxn];
41 ll bfs() {
42     ll ans=-1;
43     priority_queue<node,vector<node>,cmp>que;
44     bitset<maxn>bs;
45     que.push({0,bs});
46     struct node p;
47     while(!que.empty()) {
48         p=que.top();
49         que.pop();
50         k--;
51         if(!k) {
52             ans=p.w;
53             break;
54         }
55         int pos=0;
56         for(int i=0;i<n;i++)
57             if(p.bs[i])
58                 pos=i+1;
59         for(int i=pos;i<n;i++) {
60             if(!p.bs[i]&&( (p.bs&edge[i]) == p.bs )) {
61                 p.bs[i]=1;
62                 que.push({p.w+w[i],p.bs});
63                 p.bs[i]=0;
64             }
65         }
66     }
67     return ans;
68 }
69 int main()
70 {
71     read(n),read(k);
72     for(int i=0;i<n;i++)
73         read(w[i]);
74     for(int i=0;i<n;i++)
75         for(int j=0;j<n;j++) {
76             int x;
77             scanf("%1d",&x);
78             edge[i][j]=x;
79         }
80     write(bfs());pn;
81     return 0;
82 }
代码在这里!
原文地址:https://www.cnblogs.com/wuliking/p/11336698.html