题目链接:https://ac.nowcoder.com/acm/contest/882/D
题目大意:给出一个无向图,让你求第k小的完全子图
解题报告:
考虑什么情况下,i点可插入。
由于完全子图的性质,当前状态应当真包含和 i 相连的边,对于i的判断可以用bitset,轻松完成状态的转移。但是这样算出来会有重复的情况,所以考虑枚举顺序的问题,每次从最后一个1开始往后找情况然后转移,这样搜出来的状态就不会有重复的。
AC代码:
1 #include<bits/stdc++.h> 2 3 #define numm ch-48 4 #define pd putchar(' ') 5 #define pn putchar('\n') 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 }