Codeforces Round #454 (Div. 2, based on Technocup 2018 Elimination Round 4) E. Party [dp II][bitmasks]
题目:http://codeforces.com/contest/907/problem/E
题意:最多22个客人,每次选择一个人,可以使他的所有朋友互相都成为朋友,输出能使所有人互相都成为朋友的最少的选择次数和选择顺序
分析:数位dp,用dp[i]表示第i个状态里的人都互相是朋友所需要的最少选择次数,pre存储上一次的状态和上一次选择的人,转移的时候则需要选择已经在这个朋友圈里的人继续扩张朋友圈。要注意特判当前都已经互相为朋友的情况。
(因为数据比较小,而且合法情况非常多,也可以用随机化算法ac)
代码:
1 #define _CRT_SECURE_NO_DEPRECATE 2 #pragma comment(linker, "/STACK:102400000,102400000") 3 #include<iostream> 4 #include<cstdio> 5 #include<fstream> 6 #include<iomanip> 7 #include<algorithm> 8 #include<cmath> 9 #include<deque> 10 #include<vector> 11 #include<bitset> 12 #include<queue> 13 #include<string> 14 #include<cstring> 15 #include<map> 16 #include<stack> 17 #include<set> 18 #include<functional> 19 #define pii pair<int, int> 20 #define mod 1000000007 21 #define mp make_pair 22 #define pi acos(-1) 23 #define eps 0.00000001 24 #define mst(a,i) memset(a,i,sizeof(a)) 25 #define all(n) n.begin(),n.end() 26 #define lson(x) ((x<<1)) 27 #define rson(x) ((x<<1)|1) 28 #define inf 0x3f3f3f3f 29 typedef long long ll; 30 typedef unsigned long long ull; 31 using namespace std; 32 const int maxn = 1e5 + 5; 33 int dp[1 << 23]; 34 pii pre[1 << 23]; 35 int fri[25]; 36 int main() 37 { 38 ios::sync_with_stdio(false); 39 cin.tie(0); cout.tie(0); 40 int i, j, k, m, n; 41 cin >> n >> m; 42 int ta, tb; 43 for (int i = 1; i <= m; ++i) 44 { 45 cin >> ta >> tb; 46 ta--, tb--; 47 fri[ta] |= (1 << tb); 48 fri[tb] |= (1 << ta); 49 } 50 int mode = 1; 51 for (int i = 0; i < n; ++i) 52 { 53 if (fri[i] != (1 << n) - 1 - (1 << i))mode = 0; 54 } 55 if (mode) { cout << "0" << endl; return 0; } 56 mst(dp, -1); 57 mst(pre, -1); 58 for (int i = 0; i < n; ++i) 59 dp[1 << i] = 0, pre[1 << i] = mp(-1, -1); 60 for (int i = 1; i < (1 << n); ++i) 61 { 62 if (dp[i] == -1)continue; 63 for (int j = 0; j < n; ++j) 64 { 65 if (i >> j & 1) 66 { 67 int newmode = i | fri[j]; 68 if (dp[newmode] == -1 || (dp[newmode] > dp[i])) 69 { 70 dp[newmode] = dp[i] + 1; 71 pre[newmode] = mp(i, j); 72 } 73 } 74 } 75 } 76 cout << dp[(1 << n) - 1] << endl; 77 pii now = pre[(1 << n) - 1]; 78 vector<int>ans; 79 while (now.first != -1) 80 { 81 ans.push_back(now.second); 82 now = pre[now.first]; 83 } 84 reverse(all(ans)); 85 for (auto it : ans)cout << it+1 << " "; 86 return 0; 87 }